<!DOCTYPE html>
<html lang="en">
    <head hexo-theme='https://github.com/volantis-x/hexo-theme-volantis/#5.8.0'>
  <meta name="generator" content="Hexo 6.3.0">
  <meta name="Volantis" content="5.8.0">
  <meta charset="utf-8">
  <!-- SEO相关 -->
  
  <link rel="canonical" href="http://8.219.11.28/2024/02/23/前后端-springmvc课堂笔记/"/>
  <!-- 渲染优化 -->
    <meta http-equiv='x-dns-prefetch-control' content='on' />
      <link rel='dns-prefetch' href='https://unpkg.com'>
      <link rel="preconnect" href="https://unpkg.com" crossorigin>
  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta http-equiv="Content-Security-Policy" content=" default-src 'self' https:; block-all-mixed-content; base-uri 'self' https:; form-action 'self' https:; worker-src 'self' https:; connect-src 'self' https: *; img-src 'self' data: https: *; media-src 'self' https: *; font-src 'self' data: https: *; frame-src 'self' https: *; manifest-src 'self' https: *; child-src https:; script-src 'self' https: 'unsafe-inline' *; style-src 'self' https: 'unsafe-inline' *; ">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
  <meta content="black-translucent" name="apple-mobile-web-app-status-bar-style">
  <meta content="telephone=no" name="format-detection">
  <!-- import head_begin begin -->
  <!-- import head_begin end -->
  <!-- Custom Files headBegin begin-->
  
  <!-- Custom Files headBegin end-->
  <!-- front-matter head_begin begin -->
  <!-- front-matter head_begin end -->
  <link rel="preload" href="/css/style.css" as="style">
  <link rel="preload" href="https://unpkg.com/volantis-static@0.0.1654736714924/media/fonts/VarelaRound/VarelaRound-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous">
<link rel="preload" href="https://unpkg.com/volantis-static@0.0.1654736714924/media/fonts/UbuntuMono/UbuntuMono-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous">

  <!-- feed -->
  <!-- 页面元数据 -->
  <title>欢迎来到我的个人博客~</title>
  <meta name="keywords" content="null">
  <meta desc name="description" content="这些技术大部分是自己总结的，非官方 - 天明 - 欢迎来到我的个人博客~">
  
<meta property="og:type" content="article">
<meta property="og:title" content="欢迎来到我的个人博客~">
<meta property="og:url" content="http://8.219.11.28/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-SpringMVC%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/index.html">
<meta property="og:site_name" content="欢迎来到我的个人博客~">
<meta property="og:description" content="SpringMVC课堂笔记1、SpringMVC概述1.1 SpringMVC概念SpringMVC 也叫 Spring web mvc。是 Spring内置的一个MVC框架，在 Spring3.0 后发布。SpringMVC框架解决了WEB开发中常见的问题(参数接收、文件上传、表单验证等等)，而且使用简单，与Spring无缝集成。支持 RESTful风格的URL请求。采用了松散耦合可插拔组件结构">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png">
<meta property="article:published_time" content="2024-02-23T14:27:45.499Z">
<meta property="article:modified_time" content="2024-01-15T11:27:56.531Z">
<meta property="article:author" content="天明">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png">
  <style>
    /* 首屏样式 */
    #safearea {
  display: none;
}
:root {
  --color-site-body: #f4f4f4;
  --color-site-bg: #f4f4f4;
  --color-site-inner: #fff;
  --color-site-footer: #666;
  --color-card: #fff;
  --color-text: #444;
  --color-block: #f6f6f6;
  --color-inlinecode: #c74f00;
  --color-codeblock: #fff7ea;
  --color-h1: #3a3a3a;
  --color-h2: #3a3a3a;
  --color-h3: #333;
  --color-h4: #444;
  --color-h5: #555;
  --color-h6: #666;
  --color-p: #444;
  --color-list: #666;
  --color-list-hl: #30ad91;
  --color-meta: #888;
  --color-read-bkg: #e0d8c8;
  --color-read-post: #f8f1e2;
  --color-copyright-bkg: #f5f5f5;
}
* {
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  outline: none;
  margin: 0;
  padding: 0;
}
*::-webkit-scrollbar {
  height: 4px;
  width: 4px;
}
*::-webkit-scrollbar-track-piece {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background: #3dd9b6;
  cursor: pointer;
  border-radius: 2px;
  -webkit-border-radius: 2px;
}
*::-webkit-scrollbar-thumb:hover {
  background: #ff5722;
}
html {
  color: var(--color-text);
  width: 100%;
  height: 100%;
  font-family: UbuntuMono, "Varela Round", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, Menlo, Monaco, monospace, sans-serif;
  font-size: 16px;
}
html >::-webkit-scrollbar {
  height: 4px;
  width: 4px;
}
html >::-webkit-scrollbar-track-piece {
  background: transparent;
}
html >::-webkit-scrollbar-thumb {
  background: #54b5a0 linear-gradient(45deg, rgba(255,255,255,0.4) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.4) 50%, rgba(255,255,255,0.4) 75%, transparent 75%, transparent);
  cursor: pointer;
  border-radius: 2px;
  -webkit-border-radius: 2px;
}
html >::-webkit-scrollbar-thumb:hover {
  background: #54b5a0 linear-gradient(45deg, rgba(255,255,255,0.4) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.4) 50%, rgba(255,255,255,0.4) 75%, transparent 75%, transparent);
}
body {
  background-color: var(--color-site-body);
  text-rendering: optimizelegibility;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
}
body.modal-active {
  overflow: hidden;
}
@media screen and (max-width: 680px) {
  body.modal-active {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
  }
}
a {
  color: #2092ec;
  cursor: pointer;
  text-decoration: none;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
a:hover {
  color: #ff5722;
}
a:active,
a:hover {
  outline: 0;
}
ul,
ol {
  padding-left: 0;
}
ul li,
ol li {
  list-style: none;
}
header {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
}
img {
  border: 0;
  background: none;
  max-width: 100%;
}
svg:not(:root) {
  overflow: hidden;
}
hr {
  -moz-box-sizing: content-box;
  box-sizing: content-box;
  -webkit-box-sizing: content-box;
  -moz-box-sizing: content-box;
  height: 0;
  border: 0;
  border-radius: 1px;
  -webkit-border-radius: 1px;
  border-bottom: 1px solid rgba(68,68,68,0.1);
}
button,
input {
  color: inherit;
  font: inherit;
  margin: 0;
}
button {
  overflow: visible;
  text-transform: none;
  -webkit-appearance: button;
  cursor: pointer;
}
@supports (backdrop-filter: blur(20px)) {
  .blur {
    background: rgba(255,255,255,0.9) !important;
    backdrop-filter: saturate(200%) blur(20px);
  }
}
.shadow {
  box-shadow: 0 1px 2px 0px rgba(0,0,0,0.1);
  -webkit-box-shadow: 0 1px 2px 0px rgba(0,0,0,0.1);
}
.shadow.floatable {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
.shadow.floatable:hover {
  box-shadow: 0 2px 4px 0px rgba(0,0,0,0.1), 0 4px 8px 0px rgba(0,0,0,0.1), 0 8px 16px 0px rgba(0,0,0,0.1);
  -webkit-box-shadow: 0 2px 4px 0px rgba(0,0,0,0.1), 0 4px 8px 0px rgba(0,0,0,0.1), 0 8px 16px 0px rgba(0,0,0,0.1);
}
#l_cover {
  min-height: 64px;
}
.cover-wrapper {
  top: 0;
  left: 0;
  max-width: 100%;
  height: 100vh;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  flex-wrap: nowrap;
  -webkit-flex-wrap: nowrap;
  -khtml-flex-wrap: nowrap;
  -moz-flex-wrap: nowrap;
  -o-flex-wrap: nowrap;
  -ms-flex-wrap: nowrap;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: vertical;
  -moz-box-orient: vertical;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  align-items: center;
  align-self: center;
  align-content: center;
  color: var(--color-site-inner);
  padding: 0 16px;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  position: relative;
  overflow: hidden;
  margin-bottom: -100px;
}
.cover-wrapper .cover-bg {
  position: absolute;
  width: 100%;
  height: 100%;
  background-position: center;
  background-size: cover;
  -webkit-background-size: cover;
  -moz-background-size: cover;
}
.cover-wrapper .cover-bg.lazyload:not(.loaded) {
  opacity: 0;
  -webkit-opacity: 0;
  -moz-opacity: 0;
}
.cover-wrapper .cover-bg.lazyload.loaded {
  animation-delay: 0s;
  animation-duration: 0.5s;
  animation-fill-mode: forwards;
  animation-timing-function: ease-out;
  animation-name: fadeIn;
}
@-moz-keyframes fadeIn {
  0% {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
    filter: blur(12px);
    transform: scale(1.02);
    -webkit-transform: scale(1.02);
    -khtml-transform: scale(1.02);
    -moz-transform: scale(1.02);
    -o-transform: scale(1.02);
    -ms-transform: scale(1.02);
  }
  100% {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@-webkit-keyframes fadeIn {
  0% {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
    filter: blur(12px);
    transform: scale(1.02);
    -webkit-transform: scale(1.02);
    -khtml-transform: scale(1.02);
    -moz-transform: scale(1.02);
    -o-transform: scale(1.02);
    -ms-transform: scale(1.02);
  }
  100% {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@-o-keyframes fadeIn {
  0% {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
    filter: blur(12px);
    transform: scale(1.02);
    -webkit-transform: scale(1.02);
    -khtml-transform: scale(1.02);
    -moz-transform: scale(1.02);
    -o-transform: scale(1.02);
    -ms-transform: scale(1.02);
  }
  100% {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@keyframes fadeIn {
  0% {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
    filter: blur(12px);
    transform: scale(1.02);
    -webkit-transform: scale(1.02);
    -khtml-transform: scale(1.02);
    -moz-transform: scale(1.02);
    -o-transform: scale(1.02);
    -ms-transform: scale(1.02);
  }
  100% {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
.cover-wrapper .cover-body {
  z-index: 1;
  position: relative;
  width: 100%;
  height: 100%;
}
.cover-wrapper#full {
  height: calc(100vh + 100px);
  padding-bottom: 100px;
}
.cover-wrapper#half {
  max-height: 640px;
  min-height: 400px;
  height: calc(36vh - 64px + 200px);
}
.cover-wrapper #scroll-down {
  width: 100%;
  height: 64px;
  position: absolute;
  bottom: 100px;
  text-align: center;
  cursor: pointer;
}
.cover-wrapper #scroll-down .scroll-down-effects {
  color: #fff;
  font-size: 24px;
  line-height: 64px;
  position: absolute;
  width: 24px;
  left: calc(50% - 12px);
  text-shadow: 0 1px 2px rgba(0,0,0,0.1);
  animation: scroll-down-effect 1.5s infinite;
  -webkit-animation: scroll-down-effect 1.5s infinite;
  -khtml-animation: scroll-down-effect 1.5s infinite;
  -moz-animation: scroll-down-effect 1.5s infinite;
  -o-animation: scroll-down-effect 1.5s infinite;
  -ms-animation: scroll-down-effect 1.5s infinite;
}
@-moz-keyframes scroll-down-effect {
  0% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
  50% {
    top: -16px;
    opacity: 0.4;
    -webkit-opacity: 0.4;
    -moz-opacity: 0.4;
  }
  100% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@-webkit-keyframes scroll-down-effect {
  0% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
  50% {
    top: -16px;
    opacity: 0.4;
    -webkit-opacity: 0.4;
    -moz-opacity: 0.4;
  }
  100% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@-o-keyframes scroll-down-effect {
  0% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
  50% {
    top: -16px;
    opacity: 0.4;
    -webkit-opacity: 0.4;
    -moz-opacity: 0.4;
  }
  100% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@keyframes scroll-down-effect {
  0% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
  50% {
    top: -16px;
    opacity: 0.4;
    -webkit-opacity: 0.4;
    -moz-opacity: 0.4;
  }
  100% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
.cover-wrapper .cover-body {
  margin-top: 64px;
  margin-bottom: 100px;
}
.cover-wrapper .cover-body,
.cover-wrapper .cover-body .top,
.cover-wrapper .cover-body .bottom {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: vertical;
  -moz-box-orient: vertical;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  -webkit-justify-content: center;
  -khtml-justify-content: center;
  -moz-justify-content: center;
  -o-justify-content: center;
  -ms-justify-content: center;
  max-width: 100%;
}
.cover-wrapper .cover-body .bottom {
  margin-top: 32px;
}
.cover-wrapper .cover-body .title {
  font-family: "Varela Round", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, Helvetica, monospace;
  font-size: 3.125rem;
  line-height: 1.2;
  text-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.cover-wrapper .cover-body .subtitle {
  font-size: 20px;
}
.cover-wrapper .cover-body .logo {
  max-height: 120px;
  max-width: calc(100% - 4 * 16px);
}
@media screen and (min-height: 1024px) {
  .cover-wrapper .cover-body .title {
    font-size: 3rem;
  }
  .cover-wrapper .cover-body .subtitle {
    font-size: 1.05rem;
  }
  .cover-wrapper .cover-body .logo {
    max-height: 150px;
  }
}
.cover-wrapper .cover-body .m_search {
  position: relative;
  max-width: calc(100% - 16px);
  width: 320px;
  vertical-align: middle;
}
.cover-wrapper .cover-body .m_search .form {
  position: relative;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  width: 100%;
}
.cover-wrapper .cover-body .m_search .icon,
.cover-wrapper .cover-body .m_search .input {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
.cover-wrapper .cover-body .m_search .icon {
  position: absolute;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  line-height: 2.5rem;
  width: 32px;
  top: 0;
  left: 5px;
  color: rgba(68,68,68,0.75);
}
.cover-wrapper .cover-body .m_search .input {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  height: 2.5rem;
  width: 100%;
  box-shadow: none;
  -webkit-box-shadow: none;
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  font-size: 0.875rem;
  -webkit-appearance: none;
  padding-left: 36px;
  border-radius: 1.4rem;
  -webkit-border-radius: 1.4rem;
  background: rgba(255,255,255,0.6);
  backdrop-filter: blur(10px);
  border: none;
  color: var(--color-text);
}
@media screen and (max-width: 500px) {
  .cover-wrapper .cover-body .m_search .input {
    padding-left: 36px;
  }
}
.cover-wrapper .cover-body .m_search .input:hover {
  background: rgba(255,255,255,0.8);
}
.cover-wrapper .cover-body .m_search .input:focus {
  background: #fff;
}
.cover-wrapper .list-h {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: horizontal;
  -moz-box-orient: horizontal;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
  flex-wrap: wrap;
  -webkit-flex-wrap: wrap;
  -khtml-flex-wrap: wrap;
  -moz-flex-wrap: wrap;
  -o-flex-wrap: wrap;
  -ms-flex-wrap: wrap;
  align-items: stretch;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.cover-wrapper .list-h a {
  -webkit-box-flex: 1;
  -moz-box-flex: 1;
  -webkit-flex: 1 0;
  -ms-flex: 1 0;
  flex: 1 0;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  font-weight: 600;
}
.cover-wrapper .list-h a img {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  border-radius: 2px;
  -webkit-border-radius: 2px;
  margin: 4px;
  min-width: 40px;
  max-width: 44px;
}
@media screen and (max-width: 768px) {
  .cover-wrapper .list-h a img {
    min-width: 36px;
    max-width: 40px;
  }
}
@media screen and (max-width: 500px) {
  .cover-wrapper .list-h a img {
    margin: 2px 4px;
    min-width: 32px;
    max-width: 36px;
  }
}
@media screen and (max-width: 375px) {
  .cover-wrapper .list-h a img {
    min-width: 28px;
    max-width: 32px;
  }
}
.cover-wrapper {
  max-width: 100%;
}
.cover-wrapper.search .bottom .menu {
  margin-top: 16px;
}
.cover-wrapper.search .bottom .menu .list-h a {
  white-space: nowrap;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: horizontal;
  -moz-box-orient: horizontal;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
  align-items: baseline;
  padding: 2px;
  margin: 4px;
  color: var(--color-site-inner);
  opacity: 0.75;
  -webkit-opacity: 0.75;
  -moz-opacity: 0.75;
  text-shadow: 0 1px 2px rgba(0,0,0,0.05);
  border-bottom: 2px solid transparent;
}
.cover-wrapper.search .bottom .menu .list-h a i {
  margin-right: 4px;
}
.cover-wrapper.search .bottom .menu .list-h a p {
  font-size: 0.9375rem;
}
.cover-wrapper.search .bottom .menu .list-h a:hover,
.cover-wrapper.search .bottom .menu .list-h a.active,
.cover-wrapper.search .bottom .menu .list-h a:active {
  opacity: 1;
  -webkit-opacity: 1;
  -moz-opacity: 1;
  border-bottom: 2px solid var(--color-site-inner);
}
.cover-wrapper.dock .menu,
.cover-wrapper.featured .menu,
.cover-wrapper.focus .menu {
  border-radius: 6px;
  -webkit-border-radius: 6px;
}
.cover-wrapper.dock .menu .list-h a,
.cover-wrapper.featured .menu .list-h a,
.cover-wrapper.focus .menu .list-h a {
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: vertical;
  -moz-box-orient: vertical;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  align-items: center;
  padding: 12px;
  line-height: 24px;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  border-bottom: none;
  text-align: center;
  align-content: flex-end;
  color: rgba(68,68,68,0.7);
  font-size: 1.5rem;
}
@media screen and (max-width: 500px) {
  .cover-wrapper.dock .menu .list-h a,
  .cover-wrapper.featured .menu .list-h a,
  .cover-wrapper.focus .menu .list-h a {
    padding: 12px 8px;
  }
}
.cover-wrapper.dock .menu .list-h a i,
.cover-wrapper.featured .menu .list-h a i,
.cover-wrapper.focus .menu .list-h a i {
  margin: 8px;
}
.cover-wrapper.dock .menu .list-h a p,
.cover-wrapper.featured .menu .list-h a p,
.cover-wrapper.focus .menu .list-h a p {
  font-size: 0.875rem;
}
.cover-wrapper.dock .menu .list-h a.active,
.cover-wrapper.featured .menu .list-h a.active,
.cover-wrapper.focus .menu .list-h a.active {
  background: var(--color-card);
  backdrop-filter: none;
}
.cover-wrapper.dock .menu .list-h a.active i,
.cover-wrapper.featured .menu .list-h a.active i,
.cover-wrapper.focus .menu .list-h a.active i,
.cover-wrapper.dock .menu .list-h a.active i+p,
.cover-wrapper.featured .menu .list-h a.active i+p,
.cover-wrapper.focus .menu .list-h a.active i+p {
  color: #3dd9b6;
}
.cover-wrapper.dock .menu .list-h a.active img+p,
.cover-wrapper.featured .menu .list-h a.active img+p,
.cover-wrapper.focus .menu .list-h a.active img+p {
  color: var(--color-text);
}
.cover-wrapper.dock .menu .list-h a:hover,
.cover-wrapper.featured .menu .list-h a:hover,
.cover-wrapper.focus .menu .list-h a:hover {
  background: var(--color-card);
}
.cover-wrapper.dock .top {
  margin-bottom: 48px;
}
.cover-wrapper.dock .menu {
  background: rgba(255,255,255,0.5);
  position: absolute;
  bottom: 0;
  max-width: 100%;
}
.cover-wrapper.dock .menu .list-h {
  flex-wrap: nowrap;
  -webkit-flex-wrap: nowrap;
  -khtml-flex-wrap: nowrap;
  -moz-flex-wrap: nowrap;
  -o-flex-wrap: nowrap;
  -ms-flex-wrap: nowrap;
  margin: 4px;
}
.cover-wrapper.dock .menu .list-h a+a {
  margin-left: 4px;
}
@media screen and (max-width: 500px) {
  .cover-wrapper.dock .menu .list-h {
    overflow-x: scroll;
  }
  .cover-wrapper.dock .menu .list-h::-webkit-scrollbar {
    height: 0;
    width: 0;
  }
  .cover-wrapper.dock .menu .list-h::-webkit-scrollbar-track-piece {
    background: transparent;
  }
  .cover-wrapper.dock .menu .list-h::-webkit-scrollbar-thumb {
    background: #3dd9b6;
    cursor: pointer;
    border-radius: 0;
    -webkit-border-radius: 0;
  }
  .cover-wrapper.dock .menu .list-h::-webkit-scrollbar-thumb:hover {
    background: #ff5722;
  }
}
@supports (backdrop-filter: blur(20px)) {
  .cover-wrapper.dock .menu {
    background: rgba(255,255,255,0.5);
    backdrop-filter: saturate(200%) blur(20px);
  }
}
@font-face {
  font-family: 'UbuntuMono';
  src: url("https://unpkg.com/volantis-static@0.0.1654736714924/media/fonts/UbuntuMono/UbuntuMono-Regular.ttf");
  font-weight: 'normal';
  font-style: 'normal';
  font-display: swap;
}
@font-face {
  font-family: 'Varela Round';
  src: url("https://unpkg.com/volantis-static@0.0.1654736714924/media/fonts/VarelaRound/VarelaRound-Regular.ttf");
  font-weight: 'normal';
  font-style: 'normal';
  font-display: swap;
}
.l_header {
  position: fixed;
  z-index: 1000;
  top: 0;
  width: 100%;
  height: 64px;
  background: var(--color-card);
  box-shadow: 0 1px 2px 0px rgba(0,0,0,0.1);
  -webkit-box-shadow: 0 1px 2px 0px rgba(0,0,0,0.1);
}
.l_header.auto {
  transition: opacity 0.4s ease;
  -webkit-transition: opacity 0.4s ease;
  -khtml-transition: opacity 0.4s ease;
  -moz-transition: opacity 0.4s ease;
  -o-transition: opacity 0.4s ease;
  -ms-transition: opacity 0.4s ease;
  visibility: hidden;
}
.l_header.auto.show {
  opacity: 1 !important;
  -webkit-opacity: 1 !important;
  -moz-opacity: 1 !important;
  visibility: visible;
}
.l_header .container {
  margin-left: 16px;
  margin-right: 16px;
}
.l_header #wrapper {
  height: 100%;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.l_header #wrapper .nav-main,
.l_header #wrapper .nav-sub {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  flex-wrap: nowrap;
  -webkit-flex-wrap: nowrap;
  -khtml-flex-wrap: nowrap;
  -moz-flex-wrap: nowrap;
  -o-flex-wrap: nowrap;
  -ms-flex-wrap: nowrap;
  justify-content: space-between;
  -webkit-justify-content: space-between;
  -khtml-justify-content: space-between;
  -moz-justify-content: space-between;
  -o-justify-content: space-between;
  -ms-justify-content: space-between;
  align-items: center;
}
.l_header #wrapper .nav-main {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
.l_header #wrapper.sub .nav-main {
  transform: translateY(-64px);
  -webkit-transform: translateY(-64px);
  -khtml-transform: translateY(-64px);
  -moz-transform: translateY(-64px);
  -o-transform: translateY(-64px);
  -ms-transform: translateY(-64px);
}
.l_header #wrapper .nav-sub {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
  opacity: 0;
  -webkit-opacity: 0;
  -moz-opacity: 0;
  height: 64px;
  width: calc(100% - 2 * 16px);
  position: absolute;
}
.l_header #wrapper .nav-sub ::-webkit-scrollbar {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
}
@media screen and (min-width: 2048px) {
  .l_header #wrapper .nav-sub {
    max-width: 55vw;
    margin: auto;
  }
}
.l_header #wrapper.sub .nav-sub {
  opacity: 1;
  -webkit-opacity: 1;
  -moz-opacity: 1;
}
.l_header #wrapper .title {
  position: relative;
  color: var(--color-text);
  padding-left: 24px;
  max-height: 64px;
}
.l_header #wrapper .nav-main .title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 0;
  line-height: 64px;
  padding: 0 24px;
  font-size: 1.25rem;
  font-family: "Varela Round", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, Helvetica, monospace;
}
.l_header #wrapper .nav-main .title img {
  height: 64px;
}
.l_header .nav-sub {
  max-width: 1080px;
  margin: auto;
}
.l_header .nav-sub .title {
  font-weight: bold;
  font-family: UbuntuMono, "Varela Round", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, Menlo, Monaco, monospace, sans-serif;
  line-height: 1.2;
  max-height: 64px;
  white-space: normal;
  flex-shrink: 1;
}
.l_header .switcher {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  line-height: 64px;
  align-items: center;
}
.l_header .switcher .s-toc {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
}
@media screen and (max-width: 768px) {
  .l_header .switcher .s-toc {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: -ms-flexbox /* TWEENER - IE 10 */;
    display: -webkit-flex /* NEW - Chrome */;
    display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
    display: flex;
  }
}
.l_header .switcher >li {
  height: 48px;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
  margin: 2px;
}
@media screen and (max-width: 500px) {
  .l_header .switcher >li {
    margin: 0 1px;
    height: 48px;
  }
}
.l_header .switcher >li >a {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  justify-content: center;
  -webkit-justify-content: center;
  -khtml-justify-content: center;
  -moz-justify-content: center;
  -o-justify-content: center;
  -ms-justify-content: center;
  align-items: center;
  width: 48px;
  height: 48px;
  padding: 0.85em 1.1em;
  border-radius: 100px;
  -webkit-border-radius: 100px;
  border: none;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
  color: #3dd9b6;
}
.l_header .switcher >li >a:hover {
  border: none;
}
.l_header .switcher >li >a.active,
.l_header .switcher >li >a:active {
  border: none;
  background: var(--color-site-bg);
}
@media screen and (max-width: 500px) {
  .l_header .switcher >li >a {
    width: 36px;
    height: 48px;
  }
}
.l_header .nav-sub .switcher {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
}
.l_header .m_search {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  height: 64px;
  width: 240px;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
@media screen and (max-width: 1024px) {
  .l_header .m_search {
    width: 44px;
    min-width: 44px;
  }
  .l_header .m_search input::placeholder {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
  }
  .l_header .m_search:hover {
    width: 240px;
  }
  .l_header .m_search:hover input::placeholder {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@media screen and (min-width: 500px) {
  .l_header .m_search:hover .input {
    width: 100%;
  }
  .l_header .m_search:hover .input::placeholder {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@media screen and (max-width: 500px) {
  .l_header .m_search {
    min-width: 0;
  }
  .l_header .m_search input::placeholder {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
.l_header .m_search .form {
  position: relative;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  width: 100%;
  align-items: center;
}
.l_header .m_search .icon {
  position: absolute;
  width: 36px;
  left: 5px;
  color: var(--color-meta);
}
@media screen and (max-width: 500px) {
  .l_header .m_search .icon {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: none;
  }
}
.l_header .m_search .input {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  padding-top: 8px;
  padding-bottom: 8px;
  line-height: 1.3;
  width: 100%;
  color: var(--color-text);
  background: #fafafa;
  box-shadow: none;
  -webkit-box-shadow: none;
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  padding-left: 40px;
  font-size: 0.875rem;
  border-radius: 8px;
  -webkit-border-radius: 8px;
  border: none;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
@media screen and (min-width: 500px) {
  .l_header .m_search .input:focus {
    box-shadow: 0 4px 8px 0px rgba(0,0,0,0.1);
    -webkit-box-shadow: 0 4px 8px 0px rgba(0,0,0,0.1);
  }
}
@media screen and (max-width: 500px) {
  .l_header .m_search .input {
    background: var(--color-block);
    padding-left: 8px;
    border: none;
  }
  .l_header .m_search .input:hover,
  .l_header .m_search .input:focus {
    border: none;
  }
}
@media (max-width: 500px) {
  .l_header .m_search {
    left: 0;
    width: 0;
    overflow: hidden;
    position: absolute;
    background: #fff;
    transition: all 0.28s ease;
    -webkit-transition: all 0.28s ease;
    -khtml-transition: all 0.28s ease;
    -moz-transition: all 0.28s ease;
    -o-transition: all 0.28s ease;
    -ms-transition: all 0.28s ease;
  }
  .l_header .m_search .input {
    border-radius: 32px;
    -webkit-border-radius: 32px;
    margin-left: 16px;
    padding-left: 16px;
  }
  .l_header.z_search-open .m_search {
    width: 100%;
  }
  .l_header.z_search-open .m_search .input {
    width: calc(100% - 120px);
  }
}
ul.m-pc >li>a {
  color: inherit;
  border-bottom: 2px solid transparent;
}
ul.m-pc >li>a:active,
ul.m-pc >li>a.active {
  border-bottom: 2px solid #3dd9b6;
}
ul.m-pc li:hover >ul.list-v,
ul.list-v li:hover >ul.list-v {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
}
ul.nav-list-h {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  align-items: stretch;
}
ul.nav-list-h>li {
  position: relative;
  justify-content: center;
  -webkit-justify-content: center;
  -khtml-justify-content: center;
  -moz-justify-content: center;
  -o-justify-content: center;
  -ms-justify-content: center;
  height: 100%;
  line-height: 2.4;
  border-radius: 4px;
  -webkit-border-radius: 4px;
}
ul.nav-list-h>li >a {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-weight: 600;
}
ul.list-v {
  z-index: 1;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  position: absolute;
  background: var(--color-card);
  box-shadow: 0 2px 4px 0px rgba(0,0,0,0.08), 0 4px 8px 0px rgba(0,0,0,0.08), 0 8px 16px 0px rgba(0,0,0,0.08);
  -webkit-box-shadow: 0 2px 4px 0px rgba(0,0,0,0.08), 0 4px 8px 0px rgba(0,0,0,0.08), 0 8px 16px 0px rgba(0,0,0,0.08);
  margin-top: -6px;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  padding: 8px 0;
}
ul.list-v.show {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
}
ul.list-v hr {
  margin-top: 8px;
  margin-bottom: 8px;
}
ul.list-v >li {
  white-space: nowrap;
  word-break: keep-all;
}
ul.list-v >li.header {
  font-size: 0.78125rem;
  font-weight: bold;
  line-height: 2em;
  color: var(--color-meta);
  margin: 8px 16px 4px;
}
ul.list-v >li.header i {
  margin-right: 8px;
}
ul.list-v >li ul {
  margin-left: 0;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  margin-top: -40px;
}
ul.list-v .aplayer-container {
  min-height: 64px;
  padding: 6px 16px;
}
ul.list-v >li>a {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  color: var(--color-list);
  font-size: 0.875rem;
  font-weight: bold;
  line-height: 36px;
  padding: 0 20px 0 16px;
  text-overflow: ellipsis;
  margin: 0 4px;
  border-radius: 4px;
  -webkit-border-radius: 4px;
}
@media screen and (max-width: 1024px) {
  ul.list-v >li>a {
    line-height: 40px;
  }
}
ul.list-v >li>a >i {
  margin-right: 8px;
}
ul.list-v >li>a:active,
ul.list-v >li>a.active {
  color: var(--color-list-hl);
}
ul.list-v >li>a:hover {
  color: var(--color-list-hl);
  background: var(--color-site-bg);
}
.l_header .menu >ul>li>a {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  padding: 0 8px;
}
.l_header .menu >ul>li>a >i {
  margin-right: 4px;
}
.l_header ul.nav-list-h>li {
  color: var(--color-list);
  line-height: 64px;
}
.l_header ul.nav-list-h>li >a {
  max-height: 64px;
  overflow: hidden;
  color: inherit;
}
.l_header ul.nav-list-h>li >a:active,
.l_header ul.nav-list-h>li >a.active {
  color: #3dd9b6;
}
.l_header ul.nav-list-h>li:hover>a {
  color: var(--color-list-hl);
}
.l_header ul.nav-list-h>li i.music {
  animation: rotate-effect 1.5s linear infinite;
  -webkit-animation: rotate-effect 1.5s linear infinite;
  -khtml-animation: rotate-effect 1.5s linear infinite;
  -moz-animation: rotate-effect 1.5s linear infinite;
  -o-animation: rotate-effect 1.5s linear infinite;
  -ms-animation: rotate-effect 1.5s linear infinite;
}
@-moz-keyframes rotate-effect {
  0% {
    transform: rotate(0);
    -webkit-transform: rotate(0);
    -khtml-transform: rotate(0);
    -moz-transform: rotate(0);
    -o-transform: rotate(0);
    -ms-transform: rotate(0);
  }
  25% {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -khtml-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
    -webkit-transform: rotate(180deg);
    -khtml-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    -ms-transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -khtml-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -khtml-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
  }
}
@-webkit-keyframes rotate-effect {
  0% {
    transform: rotate(0);
    -webkit-transform: rotate(0);
    -khtml-transform: rotate(0);
    -moz-transform: rotate(0);
    -o-transform: rotate(0);
    -ms-transform: rotate(0);
  }
  25% {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -khtml-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
    -webkit-transform: rotate(180deg);
    -khtml-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    -ms-transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -khtml-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -khtml-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
  }
}
@-o-keyframes rotate-effect {
  0% {
    transform: rotate(0);
    -webkit-transform: rotate(0);
    -khtml-transform: rotate(0);
    -moz-transform: rotate(0);
    -o-transform: rotate(0);
    -ms-transform: rotate(0);
  }
  25% {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -khtml-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
    -webkit-transform: rotate(180deg);
    -khtml-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    -ms-transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -khtml-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -khtml-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
  }
}
@keyframes rotate-effect {
  0% {
    transform: rotate(0);
    -webkit-transform: rotate(0);
    -khtml-transform: rotate(0);
    -moz-transform: rotate(0);
    -o-transform: rotate(0);
    -ms-transform: rotate(0);
  }
  25% {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -khtml-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
    -webkit-transform: rotate(180deg);
    -khtml-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    -ms-transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -khtml-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -khtml-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
  }
}
.menu-phone li ul.list-v {
  right: calc(100% - 0.5 * 16px);
}
.menu-phone li ul.list-v ul {
  right: calc(100% - 0.5 * 16px);
}
#wrapper {
  max-width: 1080px;
  margin: auto;
}
@media screen and (min-width: 2048px) {
  #wrapper {
    max-width: 55vw;
  }
}
#wrapper .menu {
  -webkit-box-flex: 1;
  -moz-box-flex: 1;
  -webkit-flex: 1 1;
  -ms-flex: 1 1;
  flex: 1 1;
  margin: 0 16px 0 0;
}
#wrapper .menu .list-v ul {
  left: calc(100% - 0.5 * 16px);
}
.menu-phone {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  margin-top: 16px;
  right: 8px;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
.menu-phone ul {
  right: calc(100% - 0.5 * 16px);
}
@media screen and (max-width: 500px) {
  .menu-phone {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: block;
  }
}
.l_header {
  max-width: 65vw;
  left: calc((100% - 65vw) * 0.5);
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}
@media screen and (max-width: 2048px) {
  .l_header {
    max-width: 1112px;
    left: calc((100% - 1112px) * 0.5);
  }
}
@media screen and (max-width: 1112px) {
  .l_header {
    left: 0;
    border-radius: 0;
    -webkit-border-radius: 0;
    max-width: 100%;
  }
}
@media screen and (max-width: 500px) {
  .l_header .container {
    margin-left: 0;
    margin-right: 0;
  }
  .l_header #wrapper .nav-main .title {
    padding-left: 16px;
    padding-right: 16px;
  }
  .l_header #wrapper .nav-sub {
    width: 100%;
  }
  .l_header #wrapper .nav-sub .title {
    overflow-y: scroll;
    margin-top: 2px;
    padding: 8px 16px;
  }
  .l_header #wrapper .switcher {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: -ms-flexbox /* TWEENER - IE 10 */;
    display: -webkit-flex /* NEW - Chrome */;
    display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
    display: flex;
    margin-right: 8px;
  }
  .l_header .menu {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: none;
  }
}
@media screen and (max-width: 500px) {
  .list-v li {
    max-width: 270px;
  }
}
#u-search {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding: 60px 20px;
  z-index: 1001;
}
@media screen and (max-width: 680px) {
  #u-search {
    padding: 0px;
  }
}

  </style>
  <link rel="stylesheet" href="/css/style.css" media="print" onload="this.media='all';this.onload=null">
  <noscript><link rel="stylesheet" href="/css/style.css"></noscript>
  
<script>
if (/*@cc_on!@*/false || (!!window.MSInputMethodContext && !!document.documentMode))
    document.write(
	'<style>'+
		'html{'+
			'overflow-x: hidden !important;'+
			'overflow-y: hidden !important;'+
		'}'+
		'.kill-ie{'+
			'text-align:center;'+
			'height: 100%;'+
			'margin-top: 15%;'+
			'margin-bottom: 5500%;'+
		'}'+
    '.kill-t{'+
      'font-size: 2rem;'+
    '}'+
    '.kill-c{'+
      'font-size: 1.2rem;'+
    '}'+
		'#l_header,#l_body{'+
			'display: none;'+
		'}'+
	'</style>'+
    '<div class="kill-ie">'+
        `<span class="kill-t"><b>Sorry, your browser cannot access this site</b></span><br/>`+
        `<span class="kill-c">Microsoft has terminated support for Internet Explorer (IE) 10 and earlier versions in 2016. <br/>There are great security risks to continue using it. Please use contemporary mainstream browsers to access.</span><br/>`+
        `<a target="_blank" rel="noopener" href="https://blogs.windows.com/windowsexperience/2021/05/19/the-future-of-internet-explorer-on-windows-10-is-in-microsoft-edge/"><strong>Learn more ></strong></a>`+
    '</div>');
</script>


<noscript>
	<style>
		html{
			overflow-x: hidden !important;
			overflow-y: hidden !important;
		}
		.kill-noscript{
			text-align:center;
			height: 100%;
			margin-top: 15%;
			margin-bottom: 5500%;
		}
    .kill-t{
      font-size: 2rem;
    }
    .kill-c{
      font-size: 1.2rem;
    }
		#l_header,#l_body{
			display: none;
		}
	</style>
    <div class="kill-noscript">
        <span class="kill-t"><b>Sorry, your browser cannot access this site</b></span><br/>
        <span class="kill-c">This page requires browser support (enable) JavaScript</span><br/>
        <a target="_blank" rel="noopener" href="https://www.baidu.com/s?wd=启用JavaScript"><strong>Learn more ></strong></a>
    </div>
</noscript>


  <script>
  /************这个文件存放不需要重载的全局变量和全局函数*********/
  window.volantis = {}; // volantis 全局变量
  volantis.debug = "env"; // 调试模式
  volantis.dom = {}; // 页面Dom see: /source/js/app.js etc.

  volantis.GLOBAL_CONFIG ={
    debug: "env",
    cdn: {"js":{"app":"/js/app.js","parallax":"/js/plugins/parallax.js","rightMenu":"/js/plugins/rightMenu.js","rightMenus":"/js/plugins/rightMenus.js","sites":"/js/plugins/tags/sites.js","friends":"/js/plugins/tags/friends.js","contributors":"/js/plugins/tags/contributors.js","search":"/js/search/hexo.js"},"css":{"style":"/css/style.css"}},
    default: {"avatar":"https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/avatar/round/3442075.svg","link":"https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/link/8f277b4ee0ecd.svg","cover":"https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/cover/76b86c0226ffd.svg","image":"https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/image/2659360.svg"},
    lastupdate: new Date(1708699590610),
    sidebar: {
      for_page: ["blogger","category","tagcloud","donate"],
      for_post: ["toc"],
      webinfo: {
        lastupd: {
          enable: true,
          friendlyShow: true
        },
        runtime: {
          data: "2020/01/01",
          unit: "天"
        }
      }
    },
    plugins: {
      message: {"enable":true,"css":"https://unpkg.com/volantis-static@0.0.1654736714924/libs/izitoast/dist/css/iziToast.min.css","js":"https://unpkg.com/volantis-static@0.0.1654736714924/libs/izitoast/dist/js/iziToast.min.js","icon":{"default":"fa-solid fa-info-circle light-blue","quection":"fa-solid fa-question-circle light-blue"},"time":{"default":5000,"quection":20000},"position":"topRight","transitionIn":"bounceInLeft","transitionOut":"fadeOutRight","titleColor":"var(--color-text)","messageColor":"var(--color-text)","backgroundColor":"var(--color-card)","zindex":2147483647,"copyright":{"enable":true,"title":"知识共享许可协议","message":"请遵守 CC BY-NC-SA 4.0 协议。","icon":"far fa-copyright light-blue"},"aplayer":{"enable":true,"play":"fa-solid fa-play","pause":"fa-solid fa-pause"},"rightmenu":{"enable":true,"notice":true}},
      fancybox: {"css":"https://unpkg.com/volantis-static@0.0.1654736714924/libs/@fancyapps/ui/dist/fancybox.css","js":"https://unpkg.com/volantis-static@0.0.1654736714924/libs/@fancyapps/ui/dist/fancybox.umd.js"},
      
      
      
    }
  }

  /******************** volantis.EventListener ********************************/
  // 事件监听器 see: /source/js/app.js
  volantis.EventListener = {}
  // 这里存放pjax切换页面时将被移除的事件监听器
  volantis.EventListener.list = []
  //构造方法
  function volantisEventListener(type, f, ele) {
    this.type = type
    this.f = f
    this.ele = ele
  }
  // 移除事件监听器
  volantis.EventListener.remove = () => {
    volantis.EventListener.list.forEach(function (i) {
      i.ele.removeEventListener(i.type, i.f, false)
    })
    volantis.EventListener.list = []
  }
  /******************** volantis.dom.$ ********************************/
  // 注：这里没有选择器，也没有forEach一次只处理一个dom，这里重新封装主题常用的dom方法，返回的是dom对象，对象包含了以下方法，同时保留dom的原生API
  function volantisDom(ele) {
    if (!ele) ele = document.createElement("div")
    this.ele = ele;
    // ==============================================================
    this.ele.find = (c) => {
      let q = this.ele.querySelector(c)
      if (q)
        return new volantisDom(q)
    }
    // ==============================================================
    this.ele.hasClass = (c) => {
      return this.ele.className.match(new RegExp('(\\s|^)' + c + '(\\s|$)'));
    }
    this.ele.addClass = (c) => {
      this.ele.classList.add(c);
      return this.ele
    }
    this.ele.removeClass = (c) => {
      this.ele.classList.remove(c);
      return this.ele
    }
    this.ele.toggleClass = (c) => {
      if (this.ele.hasClass(c)) {
        this.ele.removeClass(c)
      } else {
        this.ele.addClass(c)
      }
      return this.ele
    }
    // ==============================================================
    // 参数 r 为 true 表示pjax切换页面时事件监听器将被移除，false不移除
    this.ele.on = (c, f, r = 1) => {
      this.ele.addEventListener(c, f, false)
      if (r) {
        volantis.EventListener.list.push(new volantisEventListener(c, f, this.ele))
      }
      return this.ele
    }
    this.ele.click = (f, r) => {
      this.ele.on("click", f, r)
      return this.ele
    }
    this.ele.scroll = (f, r) => {
      this.ele.on("scroll", f, r)
      return this.ele
    }
    // ==============================================================
    this.ele.html = (c) => {
      // if(c=== undefined){
      //   return this.ele.innerHTML
      // }else{
      this.ele.innerHTML = c
      return this.ele
      // }
    }
    // ==============================================================
    this.ele.hide = (c) => {
      this.ele.style.display = "none"
      return this.ele
    }
    this.ele.show = (c) => {
      this.ele.style.display = "block"
      return this.ele
    }
    // ==============================================================
    return this.ele
  }
  volantis.dom.$ = (ele) => {
    return !!ele ? new volantisDom(ele) : null;
  }
  /******************** RunItem ********************************/
  function RunItem() {
    this.list = []; // 存放回调函数
    this.start = () => {
      for (var i = 0; i < this.list.length; i++) {
        this.list[i].run();
      }
    };
    this.push = (fn, name, setRequestAnimationFrame = true) => {
      let myfn = fn
      if (setRequestAnimationFrame) {
        myfn = ()=>{
          volantis.requestAnimationFrame(fn)
        }
      }
      var f = new Item(myfn, name);
      this.list.push(f);
    };
    this.remove = (name) =>{
      for (let index = 0; index < this.list.length; index++) {
        const e = this.list[index];
        if (e.name == name) {
          this.list.splice(index,1);
        }
      }
    }
    // 构造一个可以run的对象
    function Item(fn, name) {
      // 函数名称
      this.name = name || fn.name;
      // run方法
      this.run = () => {
        try {
          fn()
        } catch (error) {
          console.log(error);
        }
      };
    }
  }
  /******************** Pjax ********************************/
  // /layout/_plugins/pjax/index.ejs
  // volantis.pjax.send(callBack[,"callBackName"]) 传入pjax:send回调函数
  // volantis.pjax.push(callBack[,"callBackName"]) 传入pjax:complete回调函数
  // volantis.pjax.error(callBack[,"callBackName"]) 传入pjax:error回调函数
  volantis.pjax = {};
  volantis.pjax.method = {
    complete: new RunItem(),
    error: new RunItem(),
    send: new RunItem(),
  };
  volantis.pjax = Object.assign(volantis.pjax, {
    push: volantis.pjax.method.complete.push,
    error: volantis.pjax.method.error.push,
    send: volantis.pjax.method.send.push,
  });
  /******************** RightMenu ********************************/
  // volantis.rightmenu.handle(callBack[,"callBackName"]) 外部菜单项控制
  // 可在 volantis.mouseEvent 处获取右键事件
  volantis.rightmenu = {};
  volantis.rightmenu.method = {
    handle: new RunItem(),
  }
  volantis.rightmenu = Object.assign(volantis.rightmenu, {
    handle: volantis.rightmenu.method.handle.push,
  });
  /********************  Dark Mode  ********************************/
  // /layout/_partial/scripts/darkmode.ejs
  // volantis.dark.mode 当前模式 dark or light
  // volantis.dark.toggle() 暗黑模式触发器
  // volantis.dark.push(callBack[,"callBackName"]) 传入触发器回调函数
  volantis.dark = {};
  volantis.dark.method = {
    toggle: new RunItem(),
  };
  volantis.dark = Object.assign(volantis.dark, {
    push: volantis.dark.method.toggle.push,
  });
  /********************  Message  ********************************/
  // VolantisApp.message
  /********************  isMobile  ********************************/
  // /source/js/app.js
  // volantis.isMobile
  // volantis.isMobileOld
  /********************脚本动态加载函数********************************/
  // volantis.js(src, cb)  cb 可以传入onload回调函数 或者 JSON对象 例如: volantis.js("src", ()=>{}) 或 volantis.js("src", {defer:true,onload:()=>{}})
  // volantis.css(src)

  // 返回Promise对象，如下方法同步加载资源，这利于处理文件资源之间的依赖关系，例如：APlayer 需要在 MetingJS 之前加载
  // (async () => {
  //     await volantis.js("...theme.plugins.aplayer.js.aplayer...")
  //     await volantis.js("...theme.plugins.aplayer.js.meting...")
  // })();

  // 已经加入了setTimeout
  volantis.js = (src, cb) => {
    return new Promise(resolve => {
      setTimeout(function () {
        var HEAD = document.getElementsByTagName("head")[0] || document.documentElement;
        var script = document.createElement("script");
        script.setAttribute("type", "text/javascript");
        if (cb) {
          if (JSON.stringify(cb)) {
            for (let p in cb) {
              if (p == "onload") {
                script[p] = () => {
                  cb[p]()
                  resolve()
                }
              } else {
                script[p] = cb[p]
                script.onload = resolve
              }
            }
          } else {
            script.onload = () => {
              cb()
              resolve()
            };
          }
        } else {
          script.onload = resolve
        }
        script.setAttribute("src", src);
        HEAD.appendChild(script);
      });
    });
  }
  volantis.css = (src) => {
    return new Promise(resolve => {
      setTimeout(function () {
        var link = document.createElement('link');
        link.rel = "stylesheet";
        link.href = src;
        link.onload = resolve;
        document.getElementsByTagName("head")[0].appendChild(link);
      });
    });
  }
  /********************按需加载的插件********************************/
  // volantis.import.jQuery().then(()=>{})
  volantis.import = {
    jQuery: () => {
      if (typeof jQuery == "undefined") {
        return volantis.js("https://unpkg.com/volantis-static@0.0.1654736714924/libs/jquery/dist/jquery.min.js")
      } else {
        return new Promise(resolve => {
          resolve()
        });
      }
    }
  }
  /********************** requestAnimationFrame ********************************/
  // 1、requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来，在一次重绘或回流中就完成，并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率，一般来说，这个频率为每秒60帧。
  // 2、在隐藏或不可见的元素中，requestAnimationFrame 将不会进行重绘或回流，这当然就意味着更少的的 cpu，gpu 和内存使用量。
  volantis.requestAnimationFrame = (fn)=>{
    if (!window.requestAnimationFrame) {
      window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame;
    }
    window.requestAnimationFrame(fn)
  }
  /************************ layoutHelper *****************************************/
  volantis.layoutHelper = (helper, html, opt)=>{
    opt = Object.assign({clean:false, pjax:true}, opt)
    function myhelper(helper, html, clean) {
      volantis.tempDiv = document.createElement("div");
      volantis.tempDiv.innerHTML = html;
      let layoutHelper = document.querySelector("#layoutHelper-"+helper)
      if (layoutHelper) {
        if (clean) {
          layoutHelper.innerHTML = ""
        }
        layoutHelper.append(volantis.tempDiv);
      }
    }
    myhelper(helper, html, opt.clean)
    if (opt.pjax) {
      volantis.pjax.push(()=>{
        myhelper(helper, html, opt.clean)
      },"layoutHelper-"+helper)
    }
  }
  /****************************** 滚动事件处理 ****************************************/
  volantis.scroll = {
    engine: new RunItem(),
    unengine: new RunItem(),
  };
  volantis.scroll = Object.assign(volantis.scroll, {
    push: volantis.scroll.engine.push,
  });
  // 滚动条距离顶部的距离
  volantis.scroll.getScrollTop = () =>{
    let scrollPos;
    if (window.pageYOffset) {
      scrollPos = window.pageYOffset;
    } else if (document.compatMode && document.compatMode != 'BackCompat') {
      scrollPos = document.documentElement.scrollTop;
    } else if (document.body) {
      scrollPos = document.body.scrollTop;
    }
    return scrollPos;
  }
  // 使用 requestAnimationFrame 处理滚动事件
  // `volantis.scroll.del` 中存储了一个数值, 该数值检测一定时间间隔内滚动条滚动的位移, 数值的检测频率是浏览器的刷新频率. 数值为正数时, 表示向下滚动. 数值为负数时, 表示向上滚动.
  volantis.scroll.handleScrollEvents = () => {
    volantis.scroll.lastScrollTop = volantis.scroll.getScrollTop()
    function loop() {
      const scrollTop = volantis.scroll.getScrollTop();
      if (volantis.scroll.lastScrollTop !== scrollTop) {
        volantis.scroll.del = scrollTop - volantis.scroll.lastScrollTop;
        volantis.scroll.lastScrollTop = scrollTop;
        // if (volantis.scroll.del > 0) {
        //   console.log("向下滚动");
        // } else {
        //   console.log("向上滚动");
        // }
        // 注销过期的unengine未滚动事件
        volantis.scroll.unengine.list=[]
        volantis.scroll.engine.start();
      }else{
        volantis.scroll.unengine.start();
      }
      volantis.requestAnimationFrame(loop)
    }
    volantis.requestAnimationFrame(loop)
  }
  volantis.scroll.handleScrollEvents()
  volantis.scroll.ele = null;
  // 触发页面滚动至目标元素位置
  volantis.scroll.to = (ele, option = {}) => {
    if (!ele) return;
    volantis.scroll.ele = ele;
    // 默认配置
    opt = {
      top: ele.getBoundingClientRect().top + document.documentElement.scrollTop,
      behavior: "smooth"
    }
    // 定义配置
    if ("top" in option) {
      opt.top = option.top
    }
    if ("behavior" in option) {
      opt.behavior = option.behavior
    }
    if ("addTop" in option) {
      opt.top += option.addTop
    }
    if (!("observerDic" in option)) {
      option.observerDic = 100
    }
    // 滚动
    window.scrollTo(opt);
    // 监视器
    // 监视并矫正元素滚动到指定位置
    // 用于处理 lazyload 引起的 cls 导致的定位失败问题
    // option.observer = false
    if (option.observer) {
      setTimeout(() => {
        if (volantis.scroll.ele != ele) {
          return
        }
        volantis.scroll.unengine.push(() => {
          let me = ele.getBoundingClientRect().top
          if(!(me >= -option.observerDic && me <= option.observerDic)){
            volantis.scroll.to(ele, option)
          }
          volantis.scroll.unengine.remove("unengineObserver")
        },"unengineObserver")
      },1000)
    }
  }
  /********************** Content Visibility ********************************/
  // 见 source/css/first.styl 如果遇到任何问题 删除 .post-story 即可
  // 一个元素被声明 content-visibility 属性后 如果元素不在 viewport 中 浏览器不会计算其后代元素样式和属性 从而节省 Style & Layout 耗时
  // content-visibility 的副作用: 锚点失效 等等(实验初期 暂不明确), 使用此方法清除样式
  volantis.cleanContentVisibility = ()=>{
    if (document.querySelector(".post-story")) {
      console.log("cleanContentVisibility");
      document.querySelectorAll(".post-story").forEach(e=>{
        e.classList.remove("post-story")
      })
    }
  }
  /******************************************************************************/
  /******************************************************************************/
  /******************************************************************************/
  //图像加载出错时的处理
  function errorImgAvatar(img) {
    img.src = "https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/avatar/round/3442075.svg";
    img.onerror = null;
  }
  function errorImgCover(img) {
    img.src = "https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/cover/76b86c0226ffd.svg";
    img.onerror = null;
  }
  /******************************************************************************/
</script>

  <!-- import head_end begin -->
  <!-- import head_end end -->
  <!-- Custom Files headEnd begin-->
  
  <!-- Custom Files headEnd end-->
  <!-- front-matter head_end begin -->
  <!-- front-matter head_end end -->
</head>
  <body itemscope itemtype="http://schema.org/WebPage">
    <!-- import body_begin begin-->
    <!-- import body_begin end-->
    <!-- Custom Files bodyBegin begin-->
    
    <!-- Custom Files bodyBegin end-->
    <!-- front-matter body_begin begin -->
    <!-- front-matter body_begin end -->
    <header itemscope itemtype="http://schema.org/WPHeader" id="l_header" class="l_header auto shadow floatable blur show" style='opacity: 0' >
  <div class='container'>
  <div id='wrapper'>
    <div class='nav-sub'>
      <p class="title"></p>
      <ul class='switcher nav-list-h m-phone' id="pjax-header-nav-list">
        <li><a id="s-comment" class="fa-solid fa-comments fa-fw" target="_self"  href="/" onclick="return false;" title="comment"></a></li>
        
          <li><a id="s-toc" class="s-toc fa-solid fa-list fa-fw" target="_self"  href="/" onclick="return false;" title="toc"></a></li>
        
      </ul>
    </div>
		<div class="nav-main">
      
        
        <a class="title flat-box" target="_self" href='/'>
          
            <img no-lazy class='logo' src='https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/Logo-NavBar@3x.png'/>
          
          
          
        </a>
      

			<div class='menu navigation'>
				<ul class='nav-list-h m-pc'>
          
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/" title="博客"
                  
                  
                  
                    active-action="action-home"
                  >
                  <i class='fa-solid fa-rss fa-fw'></i>博客
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/categories/" title="分类"
                  
                  
                  
                    active-action="action-categories"
                  >
                  <i class='fa-solid fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/tags/" title="标签"
                  
                  
                  
                    active-action="action-tags"
                  >
                  <i class='fa-solid fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/archives/" title="归档"
                  
                  
                  
                    active-action="action-archives"
                  >
                  <i class='fa-solid fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/friends/" title="友链"
                  
                  
                  
                    active-action="action-friends"
                  >
                  <i class='fa-solid fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/about/" title="关于"
                  
                  
                  
                    active-action="action-about"
                  >
                  <i class='fa-solid fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
          
				</ul>
			</div>
      
      <div class="m_search">
        <form name="searchform" class="form u-search-form">
          <i class="icon fa-solid fa-search fa-fw"></i>
          <input type="text" class="input u-search-input" placeholder="Search..." />
        </form>
      </div>
      

			<ul class='switcher nav-list-h m-phone'>
				
					<li><a class="s-search fa-solid fa-search fa-fw" target="_self" href="/" onclick="return false;" title="search"></a></li>
				
				<li>
          <a class="s-menu fa-solid fa-bars fa-fw" target="_self" href="/" onclick="return false;" title="menu"></a>
          <ul class="menu-phone list-v navigation white-box">
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/" title="博客"
                  
                  
                  
                    active-action="action-home"
                  >
                  <i class='fa-solid fa-rss fa-fw'></i>博客
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/categories/" title="分类"
                  
                  
                  
                    active-action="action-categories"
                  >
                  <i class='fa-solid fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/tags/" title="标签"
                  
                  
                  
                    active-action="action-tags"
                  >
                  <i class='fa-solid fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/archives/" title="归档"
                  
                  
                  
                    active-action="action-archives"
                  >
                  <i class='fa-solid fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/friends/" title="友链"
                  
                  
                  
                    active-action="action-friends"
                  >
                  <i class='fa-solid fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/about/" title="关于"
                  
                  
                  
                    active-action="action-about"
                  >
                  <i class='fa-solid fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
            
          </ul>
        </li>
			</ul>

      <!-- Custom Files header begin -->
      
      <!-- Custom Files header end -->
		</div>
	</div>
  </div>
</header>

    <div id="l_body">
      <div id="l_cover">
  
    
      <!-- see: /layout/_partial/scripts/_ctrl/coverCtrl.ejs -->
      <div id="none" class='cover-wrapper post dock' style="display: none;">
        
  <div class='cover-bg lazyload placeholder' data-bg="https://gcore.jsdelivr.net/gh/MHG-LAB/cron@gh-pages/bing/bing.jpg"></div>

<div class='cover-body'>
  <div class='top'>
    
    
      <p class="title">Volantis</p>
    
    
  </div>
  <div class='bottom'>
    <div class='menu navigation'>
      <div class='list-h'>
        
          
            <a href="/v4/getting-started/"
              
              
              active-action="action-v4getting-started">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f5c3.svg'><p>文档</p>
            </a>
          
            <a href="/faqs/"
              
              
              active-action="action-faqs">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f516.svg'><p>帮助</p>
            </a>
          
            <a href="/examples/"
              
              
              active-action="action-examples">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f396.svg'><p>示例</p>
            </a>
          
            <a href="/contributors/"
              
              
              active-action="action-contributors">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f389.svg'><p>社区</p>
            </a>
          
            <a href="/archives/"
              
              
              active-action="action-archives">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f4f0.svg'><p>博客</p>
            </a>
          
            <a target="_blank" rel="noopener" href="https://github.com/volantis-x/hexo-theme-volantis/"
              
              
              active-action="action-https:githubcomvolantis-xhexo-theme-volantis">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f9ec.svg'><p>源码</p>
            </a>
          
        
      </div>
    </div>
  </div>
</div>

        <div id="scroll-down" style="display: none;"><i class="fa fa-chevron-down scroll-down-effects"></i></div>
      </div>
    
  
</div>

      <div id="safearea">
        <div class="body-wrapper">
          
<div id="l_main" class=''>
  <article itemscope itemtype="http://schema.org/Article" class="article post white-box reveal md shadow floatable blur article-type-post" id="post" itemscope itemprop="blogPost">
  <link itemprop="mainEntityOfPage" href="http://8.219.11.28/2024/02/23/前后端-SpringMVC课堂笔记/">
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="欢迎来到我的个人博客~">
  </span>
  <span hidden itemprop="post" itemscope itemtype="http://schema.org/Post">
    <meta itemprop="name" content="欢迎来到我的个人博客~">
    <meta itemprop="description" content="这些技术大部分是自己总结的，非官方">
  </span>
  


  
    <span hidden>
      <meta itemprop="image" content="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png">
    </span>
  
  <div class="article-meta" id="top">
    
    
    
      <span hidden itemprop="name headline">
        
      </span>
    
  </div>


  <div id="layoutHelper-page-plugins"></div>
  <div id="post-body" itemprop="articleBody">
    <h1 id="SpringMVC课堂笔记"><a href="#SpringMVC课堂笔记" class="headerlink" title="SpringMVC课堂笔记"></a>SpringMVC课堂笔记</h1><h1 id="1、SpringMVC概述"><a href="#1、SpringMVC概述" class="headerlink" title="1、SpringMVC概述"></a>1、SpringMVC概述</h1><h2 id="1-1-SpringMVC概念"><a href="#1-1-SpringMVC概念" class="headerlink" title="1.1 SpringMVC概念"></a>1.1 SpringMVC概念</h2><p>SpringMVC 也叫 Spring web mvc。是 Spring内置的一个MVC框架，在 Spring3.0 后发布。SpringMVC框架解决了WEB开发中常见的问题(参数接收、文件上传、表单验证等等)，而且使用简单，与Spring无缝集成。支持 RESTful风格的URL请求。采用了松散耦合可插拔组件结构，比其他 MVC 框架更具扩展性和灵活性。</p>
<h2 id="1-2-SpringMVC原理"><a href="#1-2-SpringMVC原理" class="headerlink" title="1.2 SpringMVC原理"></a>1.2 SpringMVC原理</h2><p>在没有使用SpringMVC之前我们都是使用Servlet在做Web开发。但是使用Servlet开发在接收请求参数，数据共享，页面跳转等操作相对比较复杂。servlet是java进行web开发的标准，既然springMVC是对servlet的封装，那么很显然<strong>SpringMVC底层就是Servlet，SpringMVC就是对Servlet进行深层次的封装。</strong></p>
<h2 id="1-3-SpringMVC优势"><a href="#1-3-SpringMVC优势" class="headerlink" title="1.3 SpringMVC优势"></a>1.3 SpringMVC优势</h2><p>1、基于 MVC 架构，功能分工明确。解决页面代码和后台代码的分离。</p>
<p>2、简单易用。SpringMVC 也是轻量级的，jar 很小。不依赖的特定的接口和类就可以开发一个注解的 SpringMVC 项目。</p>
<p>3、作 为 Spring 框 架 一 部 分 ， 能 够 使 用Spring的IoC和AOP 。 方 便 整 合MyBatis,Hiberate,JPA等其他框架。</p>
<p>4、springMVC的注解强大易用。</p>
<h1 id="2、MVC模式回顾"><a href="#2、MVC模式回顾" class="headerlink" title="2、MVC模式回顾"></a>2、MVC模式回顾</h1><blockquote>
<p>模型1：jsp+javabean模型—在jsp页面中嵌入大量的java代码</p>
<p>模型2：jsp+servlet+javabean模型—jsp页面将请求发送给servlet，由servlet调用javabean，再由servlet将制定jsp页面响应给用户。 </p>
</blockquote>
<p>模型2一般就是现在的MVC模式，也是我们一直使用的。</p>
<p>Model-View-Controller：模型–视图–控制器</p>
<p>Model： 模型层  javaBean   负责数据访问和业务处理  dao  service  pojo</p>
<p>View：   视图   JSP技术   负责收集和展示数据</p>
<p>Controller： 控制器  servlet技术  中间调度</p>
<p> 控制器的工作：</p>
<p>1、接受客户端的请求（包括请求中携带的数据）</p>
<p>2、处理请求：调用后台的模型层中的业务逻辑</p>
<p>3、页面导航：处理完毕给出响应：JSP页面</p>
<h1 id="3、入门程序"><a href="#3、入门程序" class="headerlink" title="3、入门程序"></a>3、入门程序</h1><h2 id="3-1-创建maven项目"><a href="#3-1-创建maven项目" class="headerlink" title="3.1 创建maven项目"></a>3.1 创建maven项目</h2><p>创建项目并补齐目录结构</p>
<p><img src="/img%5Cimage-20210322182227232.png" class="lazyload" data-srcset="/img%5Cimage-20210322182227232.png" srcset="" alt="image-20210326124723582"></p>
<h2 id="3-2-pom-xml文件添加依赖和插件"><a href="#3-2-pom-xml文件添加依赖和插件" class="headerlink" title="3.2 pom.xml文件添加依赖和插件"></a>3.2 pom.xml文件添加依赖和插件</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--web项目--&gt;</span>	</span><br><span class="line"><span class="tag">&lt;<span class="name">packaging</span>&gt;</span>war<span class="tag">&lt;/<span class="name">packaging</span>&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">       <span class="comment">&lt;!--spring-webmvc依赖--&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-webmvc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.2.13.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">       <span class="comment">&lt;!--springmvc底层还是servlet，所以必须添加serlvet依赖--&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>javax.servlet<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>javax.servlet-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.0.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">scope</span>&gt;</span>provided<span class="tag">&lt;/<span class="name">scope</span>&gt;</span><span class="comment">&lt;!--插件运行的时候没有scope，插件启动可能会失败--&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">           <span class="comment">&lt;!-- 编码和编译和JDK版本 --&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.8.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                   <span class="tag">&lt;<span class="name">source</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">source</span>&gt;</span></span><br><span class="line">                   <span class="tag">&lt;<span class="name">target</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">target</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">           <span class="comment">&lt;!--tomcat插件--&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.tomcat.maven<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>tomcat7-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                   <span class="tag">&lt;<span class="name">path</span>&gt;</span>/<span class="tag">&lt;/<span class="name">path</span>&gt;</span></span><br><span class="line">                   <span class="tag">&lt;<span class="name">port</span>&gt;</span>8080<span class="tag">&lt;/<span class="name">port</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="3-3-创建Spring和SpringMVC的配置文件"><a href="#3-3-创建Spring和SpringMVC的配置文件" class="headerlink" title="3.3 创建Spring和SpringMVC的配置文件"></a>3.3 创建Spring和SpringMVC的配置文件</h2><p>我们一般将除了 Controller 之外的所有 Bean 注册到 Spring 容器中，而将 Controller 注册到 SpringMVC 容器中。所以我们在 resources 目录下添加 applicationContext.xml 作为 spring 的配置，添加springmvc.xml作为springmvc的配置文件。</p>
<h3 id="3-3-1-创建Spring配置文件applicationContext-xml文件"><a href="#3-3-1-创建Spring配置文件applicationContext-xml文件" class="headerlink" title="3.3.1 创建Spring配置文件applicationContext.xml文件"></a>3.3.1 创建Spring配置文件applicationContext.xml文件</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">        &quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--spring的配置文件:除了控制器之外的bean对象都在这里扫描--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.lina.dao,com.lina.service&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="3-3-2-创建SpringMVC的配置文件springmvc-xml"><a href="#3-3-2-创建SpringMVC的配置文件springmvc-xml" class="headerlink" title="3.3.2 创建SpringMVC的配置文件springmvc.xml"></a>3.3.2 创建SpringMVC的配置文件springmvc.xml</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:mvc</span>=<span class="string">&quot;http://www.springframework.org/schema/mvc&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">        &quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--springmvc的配置文件:控制器的bean对象都在这里扫描--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.lina.controller&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="3-4-在web-xml中进行Spring和SpringMVC配置"><a href="#3-4-在web-xml中进行Spring和SpringMVC配置" class="headerlink" title="3.4 在web.xml中进行Spring和SpringMVC配置"></a>3.4 在web.xml中进行Spring和SpringMVC配置</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">    <span class="comment">&lt;!--spring的配置--&gt;</span>	</span><br><span class="line"><span class="tag">&lt;<span class="name">context-param</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--contextConfigLocation：表示用于加载 Bean的配置文件--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>contextConfigLocation<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--指定spring配置文件的位置</span></span><br><span class="line"><span class="comment">            这个配置文件也有一些默认规则，它的配置文件名默认就叫 applicationContext.xml ，如果将这个配置文件放在 WEB-INF 目录下，那么这里就可以不用				指定配置文件位置，只需要指定监听器就可以。</span></span><br><span class="line"><span class="comment">            这段配置是 Spring 集成 Web 环境的通用配置；一般用于加载除控制器层的 Bean（如dao、service 等），以便于与其他任何Web框架集成。</span></span><br><span class="line"><span class="comment">        --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>classpath:applicationContext.xml<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">context-param</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">listener</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">listener-class</span>&gt;</span>org.springframework.web.context.ContextLoaderListener<span class="tag">&lt;/<span class="name">listener-class</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">listener</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--SpringMVC的配置--&gt;</span>	</span><br><span class="line">	<span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment">        前端控制器：所有的请求都会经过此控制器，然后通过此控制器分发到各个分控制器.</span></span><br><span class="line"><span class="comment">          前端控制器本质上还是一个Servlet，因为SpringMVC底层就是使用Servlet编写的</span></span><br><span class="line"><span class="comment">    --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">servlet-name</span>&gt;</span>dispatcherServlet<span class="tag">&lt;/<span class="name">servlet-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">servlet-class</span>&gt;</span>org.springframework.web.servlet.DispatcherServlet<span class="tag">&lt;/<span class="name">servlet-class</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 创建前端控制器的时候读取springmvc配置文件启动ioc容器 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>contextConfigLocation<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>classpath*:springmvc.xml<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- Tomcat启动完毕就创建此对象 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">load-on-startup</span>&gt;</span>1<span class="tag">&lt;/<span class="name">load-on-startup</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">servlet</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 配置拦截路径url，所有以.do结尾的请求都会被前端控制器拦截处理 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet-mapping</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">servlet-name</span>&gt;</span>dispatcherServlet<span class="tag">&lt;/<span class="name">servlet-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>*.do<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">servlet-mapping</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment">SpringMVC的配置解析：</span></span><br><span class="line"><span class="comment">	1、servlet-class：前端控制器的完全限定名，在spring-webmvc-5.2.13.RELEASE.jar包中的org.springframework.web.servlet下</span></span><br><span class="line"><span class="comment">	2、load-on-startup：标记是否在Web服务器（这里是Tomcat）启动时会创建这个 Servlet 实例，即是否在 Web 服务器启动时调用执行该 Servlet 的 init()方</span></span><br><span class="line"><span class="comment">法，而不是在真正访问时才创建。	要求取值是整数。</span></span><br><span class="line"><span class="comment">		值大于0：表示容器在启动时就加载并初始化这个 servlet，数值越小，该 Servlet的优先级就越高，其被创建的也就越早</span></span><br><span class="line"><span class="comment">		值小于0或者省略：表示该 Servlet 在真正被使用时才会去创建。</span></span><br><span class="line"><span class="comment">		值相同：容器会自己选择创建顺序</span></span><br><span class="line"><span class="comment">	3、url-pattern：可以写为 / ，可以写为*.do 、*.action、*.mvc等形式，此处先写*.do,以后介绍不同写法的区别。</span></span><br><span class="line"><span class="comment">	4、init-param：表示了springmvc配置文件的名称和位置。如果没有配置，默认在项目的WEB-INF 目录下找名称为 Servlet 名称-servlet.xml 的配置文件。</span></span><br><span class="line"><span class="comment">		如果没有配置，启用默认的规则：即如果配置文件放在 webapp/WEB-INF/ 目录下，并且配置文件的名字等于 DispatcherServlet 的名字+ -servlet（即这里的配置文件路径是 webapp/WEB-INF/dispatcherServlet-servlet.xml），如果是这样的话，可以不用添加 init-param 参数，即不用手动配置 springmvc 的配置文件，框架会自动加载。</span></span><br><span class="line"><span class="comment">		而一般情况下，配置文件是放在类路径下，即 resources 目录下。所以，在注册前端控制器时，还需要设置查找 SpringMVC 配置文件路径。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">		其中contextConfigLocation属性：来自DispatcherServlet的父类FrameworkServlet，该类中的contextConfigLocation属性用来配置springmvc的路径和名称。</span></span><br><span class="line"><span class="comment">--&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="3-5-创建控制器"><a href="#3-5-创建控制器" class="headerlink" title="3.5 创建控制器"></a>3.5 创建控制器</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.lina.service.TeamService;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: TeamController</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeamController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TeamService teamService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;hello.do&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">add</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;TeamController----add---&quot;</span>);</span><br><span class="line">        teamService.add();</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.addObject(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;湖人&quot;</span>);<span class="comment">//相当于request.setAttrubuite(&quot;teanName&quot;,&quot;湖人&quot;);</span></span><br><span class="line">        mv.setViewName(<span class="string">&quot;index&quot;</span>);<span class="comment">//未来经过springmvc的视图解析器处理，转换成物理资源路径,相当于request.getRequestDispatcher(&quot;index.jsp&quot;).forward();</span></span><br><span class="line">        <span class="comment">//经过InternalResourceViewResolver对象的处理之后加上前后缀就变为了   /jsp/index.jsp</span></span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeamService</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;TeamService---- add-----&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3-6-配置视图解析器"><a href="#3-6-配置视图解析器" class="headerlink" title="3.6 配置视图解析器"></a>3.6 配置视图解析器</h2><p>在springmvc.xml配置文件中添加视图解析器的配置</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--视图解析器--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;internalResourceViewResolver&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.web.servlet.view.InternalResourceViewResolver&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;prefix&quot;</span> <span class="attr">value</span>=<span class="string">&quot;/&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;suffix&quot;</span> <span class="attr">value</span>=<span class="string">&quot;.jsp&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">     <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"> <span class="tag">&lt;<span class="name">mvc:annotation-driven</span>/&gt;</span></span><br><span class="line"><span class="comment">&lt;!--annotation-driven是一种简写形式，也可以手动配置替代这种简写形式，简写形式可以让初学者快速应用默认配置方案。</span></span><br><span class="line"><span class="comment">	该注解会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter两个bean,是springMVC为@Controller分发用户请求所必须的，解决了@Controller注解使用的前提配置。</span></span><br><span class="line"><span class="comment">同时它还提供了：数据绑定支持，@NumberFormatannotation支持，@DateTimeFormat支持，@Valid支持，读写XML的支持（JAXB，读写JSON的支持（Jackson）。我们处理响应ajax请求时，就使用到了对json的支持（配置之后，在加入了jackson的core和mapper包之后，不写配置文件也能自动转换成json）。</span></span><br><span class="line"><span class="comment">--&gt;</span>   </span><br></pre></td></tr></table></figure>

<h2 id="3-7-编写index-jsp页面"><a href="#3-7-编写index-jsp页面" class="headerlink" title="3.7 编写index.jsp页面"></a>3.7 编写index.jsp页面</h2><p>webapp文件夹下面创建文件夹jsp,然后jsp文件夹中添加index.jsp页面</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;index&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;h1&gt;index---------------$&#123;teamName&#125;&lt;/h1&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<h2 id="3-8-测试"><a href="#3-8-测试" class="headerlink" title="3.8 测试"></a>3.8 测试</h2><p><img src="/img%5Cimage-20210326164249440.png" class="lazyload" data-srcset="/img%5Cimage-20210326164249440.png" srcset="" alt="image-20210326164249440"></p>
<p>将刚刚的地址复制到浏览器之后追加控制中add方法的访问路径hello.do,看到如下页面表示运行成功！</p>
<p><img src="/img%5Cimage-20210326164315950.png" class="lazyload" data-srcset="/img%5Cimage-20210326164315950.png" srcset="" alt="image-20210326164315950"></p>
<h2 id="3-9-解析"><a href="#3-9-解析" class="headerlink" title="3.9 解析"></a>3.9 解析</h2><p>当 Spring 和 SpringMVC 同时出现，我们的项目中将存在两个容器，一个是 <strong>Spring 容器</strong>，另一个是 <strong>SpringMVC 容器</strong>，Spring 容器通过 ContextLoaderListener 来加载，SpringMVC 容器则通过 DispatcherServlet 来加载，这两个容器不一样：</p>
<p><img src="/img%5Cimage-20210322193305736.png" class="lazyload" data-srcset="/img%5Cimage-20210322193305736.png" srcset="" alt="image-20210326183914717"></p>
<p>如图所示：</p>
<ul>
<li>ContextLoaderListener 初始化的上下文加载的 Bean 是对于整个应用程序共享的，不管是使用什么表现层技术，一般如 dao层、service层 的bean；</li>
<li>DispatcherServlet 初始化的上下文加载的 bean 是只对 Spring Web MVC 有效的 bean，如 Controller、HandlerMapping、HandlerAdapter 等等，该初始化上下文应该只加载 Web相关组件。</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">1.Spring容器中不能扫描所有Bean嘛？</span><br><span class="line">	不可以。当用户发送的请求达到服务端后，会寻找前端控制器DispatcherServlet去处理，只在SpringMVC容器中找，所以Controller必须在SpringMVC容器中扫描。</span><br><span class="line"></span><br><span class="line">2.SpringMVC容器中可以扫描所有Bean嘛？</span><br><span class="line">	可以。可以在SpringMVC容器中扫描所有Bean。但是实际开发中一般不会这么做，原因如下：</span><br><span class="line">	（1）为了方便配置文件的管理</span><br><span class="line">	（2）未来在 Spring+SpringMVC+Mybatis组合中，要写的配置内容很多，一般都会根据功能分开编写</span><br></pre></td></tr></table></figure>

<h1 id="4、SpringMVC工作流程"><a href="#4、SpringMVC工作流程" class="headerlink" title="4、SpringMVC工作流程"></a>4、SpringMVC工作流程</h1><h2 id="4-1-工作流程分析"><a href="#4-1-工作流程分析" class="headerlink" title="4.1 工作流程分析"></a>4.1 工作流程分析</h2><p><img src="/img%5Cimage-20210325163623741.png" class="lazyload" data-srcset="/img%5Cimage-20210325163623741.png" srcset="" alt="image-20210326183937118"></p>
<p>（1）用户通过浏览器发送请求到前端控制器DispatcherServlet。</p>
<p>（2）前端控制器直接将请求转给处理器映射器HandleMapping。</p>
<p>（3）处理器映射器HandleMapping会根据请求，找到负责处理该请求的处理器，并将其封装为处理器执行链HandlerExecutionChina后返回给前端控制器DispatcherServlet。</p>
<p>（4）前端控制器DispatcherServlet根据处理器执行链中的处理器，找到能够执行该处理器的处理器适配器HandlerAdaptor。</p>
<p>（5）处理器适配器HandlerAdaptor调用执行处理器Controller。</p>
<p>（6）处理器Controller将处理结果及要跳转的视图封装到一个对象 ModelAndView 中，并将其返回给处理器适配器HandlerAdaptor。</p>
<p>（7）处理器适配器直接将结果返回给前端控制器DispatcherServlet。</p>
<p>（8）前端控制器调用视图解析器，将 ModelAndView 中的视图名称封装为视图对象。</p>
<p>（9）视图解析器ViewResolver将封装了的视图View对象返回给前端控制器DispatcherServlet.</p>
<p>（10）前端控制器DispatcherServlet调用视图对象，让其自己进行渲染，即进行数据填充，形成响应对象。</p>
<p>（11）前端控制器响应浏览器。</p>
<h2 id="4-2-SpringMVC组件"><a href="#4-2-SpringMVC组件" class="headerlink" title="4.2 SpringMVC组件"></a>4.2 SpringMVC组件</h2><p>1.DispatcherServlet：前端控制器,也称为中央控制器或者核心控制器。</p>
<p><strong>用户请求的入口控制器</strong>，它就相当于 mvc 模式中的c，DispatcherServlet 是整个流程控制的中心，相当于是 SpringMVC 的大脑，由它调用其它组件处理用户的请求，DispatcherServlet 的存在降低了组件之间的耦合性。SpringMVC框架提供的该核心控制器需要我们在web.xml文件中配置。</p>
<p>2.HandlerMapping：处理器映射器</p>
<p>HandlerMapping也是控制器，派发请求的控制器。我们不需要自己控制该类，但是他是springmvc运转历程中的重要的一个控制器。 HandlerMapping负责根据用户请求找到 Handler 即处理器（也就是我们所说的 Controller），SpringMVC 提供了不同的映射器实现不同的映射方式，例如：配置文件方式，实现接口方式，注解方式等，在实际开发中，我们常用的方式是注解方式。</p>
<p>3.Handler：处理器</p>
<p>Handler 是继 DispatcherServlet 前端控制器的后端控制器，在DispatcherServlet 的控制下 Handler 对具体的用户请求进行处理。由于 Handler 涉及到具体的用户业务请求，所以一般情况需要程序员根据业务需求开发 Handler。（这里所说的 Handler 就是指我们的 Controller）</p>
<p>4.HandlAdapter：处理器适配器</p>
<p>通过 HandlerAdapter 对处理器进行执行，这是适配器模式的应用，通过扩展处理器适配器，支持更多类型的处理器,调用处理器传递参数等工作。</p>
<p>5.ViewResolver：视图解析器</p>
<p>ViewResolver 负责将处理结果生成 View 视图，ViewResolver 首先根据逻辑视图名解析成物理视图名称，即具体的页面地址，再生成 View 视图对象，最后对 View 进行渲染将处理结果通过页面展示给用户。 SpringMVC 框架提供了很多的 View 视图类型，包括：jstlView、freemarkerView、pdfView 等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户，需要由程序员根据业务需求开发具体的页面。</p>
<h1 id="5-RequestMapping-注解"><a href="#5-RequestMapping-注解" class="headerlink" title="5  @RequestMapping 注解"></a>5  @RequestMapping 注解</h1><h2 id="5-1-RequestMapping出现的位置"><a href="#5-1-RequestMapping出现的位置" class="headerlink" title="5.1@RequestMapping出现的位置"></a>5.1@RequestMapping出现的位置</h2><p>过@RequestMapping 注解定义了处理器对于请求的映射规则。该注解可以定义在类上，也可以定义在方法上，但是含义不同。</p>
<p><img src="/img%5Cimage-20210323115519302.png" class="lazyload" data-srcset="/img%5Cimage-20210323115519302.png" srcset="" alt="image-20210323115519302"></p>
<p>一个@Controller 所注解的类中，可以定义多个处理器方法。当然，不同的处理器方法所匹配的 URI 是不同的。这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的value 属性中。但若这些请求具有相同的 URI 部分，则这些相同的 URI，可以被抽取到注解在类之上的RequestMapping 的 value 属性中。此时的这个 URI 表示模块的名称。URI 的请求是相对于 Web 的根目录。在类的级别上的注解会将一个特定请求或者请求模式映射到一个控制器之上。之后你还可以另外添加方法级别的注解来进一步指定到处理方法的映射关系。</p>
<p>示例：修改TeamController.java 如下</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.lina.service.TeamService;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMethod;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;team&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeamController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TeamService teamService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(value = &quot;add.do&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">addTeam</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;TeamController----addTeam---&quot;</span>);</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.setViewName(<span class="string">&quot;team/add&quot;</span>);<span class="comment">//    映射成为物理资源路径：/jsp/team/add.jsp</span></span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@RequestMapping(value = &quot;update.do&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">updateTeam</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;TeamController----updateTeam---&quot;</span>);</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.setViewName(<span class="string">&quot;team/update&quot;</span>);<span class="comment">//映射成为物理资源路径：/jsp/team/update.jsp</span></span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;hello.do&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">hello</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;TeamController----add---&quot;</span>);</span><br><span class="line">        teamService.add();</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.addObject(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;湖人&quot;</span>);<span class="comment">//相当于request.setAttrubuite(&quot;teanName&quot;,&quot;湖人&quot;);</span></span><br><span class="line">        mv.setViewName(<span class="string">&quot;index&quot;</span>);<span class="comment">//未来经过springmvc的视图解析器处理，转换成物理资源路径,相当于request.getRequestDispatcher(&quot;index.jsp&quot;).forward();</span></span><br><span class="line">        <span class="comment">//经过InternalResourceViewResolver对象的处理之后加上前后缀就变为了   /jsp/index.jsp</span></span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><img src="/img%5Cimage-20210323121029513.png" class="lazyload" data-srcset="/img%5Cimage-20210323121029513.png" srcset="" alt="image-20210326195351062"></p>
<p>浏览器中访问：</p>
<p><img src="/img%5Cimage-20210323121729051.png" class="lazyload" data-srcset="/img%5Cimage-20210323121729051.png" srcset="" alt="image-20210326195909844"></p>
<h2 id="5-2-指定请求提交方式"><a href="#5-2-指定请求提交方式" class="headerlink" title="5.2 指定请求提交方式"></a>5.2 指定请求提交方式</h2><p>@RequestMapping的method属性，用来对被注解方法所处理请求的提交方式进行限制，即只有满足method 属性指定的提交方式的请求，才会执行该被注解方法。</p>
<p>Method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GET 与</p>
<p>RequestMethod.POST，分别表示提交方式的匹配规则为 GET 与 POST 提交。</p>
<p><img src="/img%5Cimage-20210323122355399.png" class="lazyload" data-srcset="/img%5Cimage-20210323122355399.png" srcset="" alt="image-20210326200350095"></p>
<p><img src="/img%5Cimage-20210323122546650.png" class="lazyload" data-srcset="/img%5Cimage-20210323122546650.png" srcset="" alt="image-20210326200520004"></p>
<p>以下表格列出了常用的提交方式：</p>
<table>
<thead>
<tr>
<th>请求方式</th>
<th>提交方式</th>
</tr>
</thead>
<tbody><tr>
<td>地址栏请求</td>
<td>get请求</td>
</tr>
<tr>
<td>超链接请求</td>
<td>get请求</td>
</tr>
<tr>
<td>表单请求</td>
<td>默认get，可以指定post</td>
</tr>
<tr>
<td>AJAX请求</td>
<td>默认get，可以指定post</td>
</tr>
</tbody></table>
<h2 id="5-3-补充url-pattern解析"><a href="#5-3-补充url-pattern解析" class="headerlink" title="5.3 补充url-pattern解析"></a>5.3 补充url-pattern解析</h2><h3 id="5-3-1-url-pattern解析"><a href="#5-3-1-url-pattern解析" class="headerlink" title="5.3.1 url-pattern解析"></a>5.3.1 url-pattern解析</h3><p>在web.xml配置SpringMVC的前端控制器时有<url-pattern/>这个节点。这个节点中的值一般有两种写法：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">1、*.do</span><br><span class="line">	在没有特殊要求的情况下，SpringMVC 的前端控制器 DispatcherServlet 的常使用后辍匹配方式，可以写为*.do 或者 *.action, *.mvc 等。</span><br><span class="line"></span><br><span class="line">2、/</span><br><span class="line">	可以写为/，但是 DispatcherServlet 会将向静态内容--例如.css、.js、图片等资源的获取请求时，也会当作是一个普通的 Controller 请求。前端控制器会调用处理器映射器为其查找相应的处理器。肯定找不到啊，所以所有的静态资源获取请求也均会报 404 错误。</span><br></pre></td></tr></table></figure>

<p>案例：在index.jsp页面添加一张图片，如果<url-pattern>节点中的值为*.do,图片可以正常访问，但是如果为&#x2F;就不能访问。</p>
<p>1、项目中添加图片，同时修改index.jsp页面</p>
<p><img src="/img%5Cimage-20210326203432966.png" class="lazyload" data-srcset="/img%5Cimage-20210326203432966.png" srcset="" alt="image-20210326203432966"></p>
<p>2、修改web.xml</p>
<p><img src="/img%5Cimage-20210326203610025.png" class="lazyload" data-srcset="/img%5Cimage-20210326203610025.png" srcset="" alt="image-20210326203610025"></p>
<p>3、此时访问图片无法显示</p>
<h3 id="5-3-2-静态资源访问"><a href="#5-3-2-静态资源访问" class="headerlink" title="5.3.2 静态资源访问"></a>5.3.2 静态资源访问</h3><p>如果<url-pattern/>的值配置为&#x2F;后，静态资源可以通过以下两种方法解决。</p>
<h4 id="5-3-2-1使用-mvc-default-servlet-handler"><a href="#5-3-2-1使用-mvc-default-servlet-handler" class="headerlink" title="5.3.2.1使用&lt; mvc:default-servlet-handler&#x2F; &gt;"></a>5.3.2.1使用&lt; mvc:default-servlet-handler&#x2F; &gt;</h4><p>在springmvc的配置文件中添加如下内容：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">mvc:default-servlet-handler</span>/&gt;</span></span><br><span class="line"><span class="comment">&lt;!--声 明 了 &lt;mvc:default-servlet-handler /&gt; 后 ，springmvc框架会在容器中创建DefaultServletHttpRequestHandler处理器对象。该对象会对所有进入 DispatcherServlet的URL进行检查。如果发现是静态资源的请求，就将该请求转由Web应用服务器默认的Servlet 处理。</span></span><br><span class="line"><span class="comment">一般的服务器都有默认的 Servlet。例如咱们使用的Tomcat服务器中，有一个专门用于处理静态资源访问的 Servlet 名叫 DefaultServlet。其&lt;servlet-name/&gt;为default。可以处理各种静态资源访问请求。该Servlet注册在 Tomcat 服务器的 web.xml 中。在 Tomcat安装目录/conf/web.xml。--&gt;</span></span><br></pre></td></tr></table></figure>

<p><img src="/img%5Cimage-20210326204221313.png" class="lazyload" data-srcset="/img%5Cimage-20210326204221313.png" srcset="" alt="image-20210326204344938"></p>
<h4 id="5-3-2-2-使用-mvc-resources"><a href="#5-3-2-2-使用-mvc-resources" class="headerlink" title="5.3.2.2 使用 &lt; mvc:resources&#x2F; &gt;"></a>5.3.2.2 使用 &lt; mvc:resources&#x2F; &gt;</h4><p>在springmvc的配置文件中添加如下内容：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> <span class="tag">&lt;<span class="name">mvc:resources</span> <span class="attr">location</span>=<span class="string">&quot;/images/&quot;</span> <span class="attr">mapping</span>=<span class="string">&quot;/images/**&quot;</span> /&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- </span></span><br><span class="line"><span class="comment">	location: 表示静态资源所在目录。当然，目录不要使用/WEB-INF/及其子目录。</span></span><br><span class="line"><span class="comment">	mapping: 表示对该资源的请求。注意，后面是两个星号**。--&gt;</span></span><br></pre></td></tr></table></figure>

<p>在 Spring3.0 版本后，Spring 定义了专门用于处理静态资源访问请求的处理器ResourceHttpRequestHandler。并且添加了&lt; mvc:resources&#x2F; &gt;标签，专门用于解决静态资源无法访问问题。</p>
<h1 id="6、处理器方法的参数"><a href="#6、处理器方法的参数" class="headerlink" title="6、处理器方法的参数"></a>6、处理器方法的参数</h1><p>处理器方法可以包含以下四类参数，这些参数会在系统调用时由系统自动赋值.所以我们可以在方法内直接使用。以下是这四类参数:</p>
<ul>
<li>HttpServletRequest</li>
<li>HttpServletResponse</li>
<li>HttpSession</li>
<li>请求中所携带的请求参数</li>
</ul>
<p>准备工作：创建新的控制器ParamController.java和前端页面hello.jsp页面</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;param&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ParamController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;hello&quot;)</span></span><br><span class="line">    <span class="keyword">public</span>  ModelAndView <span class="title function_">hello</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;hello);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure>

<h2 id="6-1-直接使用方法的参数逐个接收"><a href="#6-1-直接使用方法的参数逐个接收" class="headerlink" title="6.1 直接使用方法的参数逐个接收"></a>6.1 直接使用方法的参数逐个接收</h2><h2 id="6-2-使用对象接收多个参数"><a href="#6-2-使用对象接收多个参数" class="headerlink" title="6.2 使用对象接收多个参数"></a>6.2 使用对象接收多个参数</h2><h2 id="6-3-请求参数和方法名称的参数不一致"><a href="#6-3-请求参数和方法名称的参数不一致" class="headerlink" title="6.3 请求参数和方法名称的参数不一致"></a>6.3 请求参数和方法名称的参数不一致</h2><h2 id="6-4-使用HttpServletRequest-对象获取参数"><a href="#6-4-使用HttpServletRequest-对象获取参数" class="headerlink" title="6.4 使用HttpServletRequest 对象获取参数"></a>6.4 使用HttpServletRequest 对象获取参数</h2><h2 id="6-5-直接使用URL地址传参"><a href="#6-5-直接使用URL地址传参" class="headerlink" title="6.5 直接使用URL地址传参"></a>6.5 直接使用URL地址传参</h2><h2 id="6-6-获取日期类型的参数"><a href="#6-6-获取日期类型的参数" class="headerlink" title="6.6 获取日期类型的参数"></a>6.6 获取日期类型的参数</h2><h2 id="6-7-获取数组类型的参数"><a href="#6-7-获取数组类型的参数" class="headerlink" title="6.7 获取数组类型的参数"></a>6.7 获取数组类型的参数</h2><h2 id="6-8-获取集合类型的参数"><a href="#6-8-获取集合类型的参数" class="headerlink" title="6.8 获取集合类型的参数"></a>6.8 获取集合类型的参数</h2><p>SpringMVC不支持直接从参数中获取对象集合类型，需要将对象集合封装到实体类中。</p>
<p>案例源码：</p>
<p>修改实体类Team.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.pojo;</span><br><span class="line"><span class="keyword">import</span> org.springframework.format.annotation.DateTimeFormat;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Team</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Integer teamId;</span><br><span class="line">    <span class="keyword">private</span> String teamName;</span><br><span class="line">    <span class="keyword">private</span> String location;</span><br><span class="line">    <span class="meta">@DateTimeFormat(pattern = &quot;yyyy-MM-dd&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> Date createTime;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Team&#123;&quot;</span> +</span><br><span class="line">                <span class="string">&quot;teamId=&quot;</span> + teamId +</span><br><span class="line">                <span class="string">&quot;, teamName=&#x27;&quot;</span> + teamName + <span class="string">&#x27;\&#x27;&#x27;</span> +</span><br><span class="line">                <span class="string">&quot;, location=&#x27;&quot;</span> + location + <span class="string">&#x27;\&#x27;&#x27;</span> +</span><br><span class="line">                <span class="string">&quot;, createTime=&quot;</span> + createTime +</span><br><span class="line">                <span class="string">&#x27;&#125;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="comment">//省略set get方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>创建实体类QueryVO.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.vo;</span><br><span class="line"><span class="keyword">import</span> com.lina.pojo.Team;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">QueryVO</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;Team&gt; teamList;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> List&lt;Team&gt; <span class="title function_">getTeamList</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> teamList;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setTeamList</span><span class="params">(List&lt;Team&gt; teamList)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.teamList = teamList;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>前端页面hello.jsp</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;hello&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line"></span><br><span class="line">    &lt;h3&gt;<span class="number">8</span>、获取集合类型的参数&lt;/h3&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/param/test08&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">        球队名称<span class="number">1</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称<span class="number">2</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称<span class="number">3</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;提交&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/param/test09&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">        球队id1：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamList[0].teamId&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队id2：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamList[1].teamId&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队id3：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamList[2].teamId&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称<span class="number">1</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamList[0].teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称<span class="number">2</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamList[1].teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称<span class="number">3</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamList[2].teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;提交&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">    &lt;h3&gt;<span class="number">7</span>、获取数组类型的参数&lt;/h3&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/param/test07&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">        球队名称<span class="number">1</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称<span class="number">2</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称<span class="number">3</span>：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;提交&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">    &lt;h3&gt;<span class="number">6</span>、获取日期类型的参数&lt;/h3&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/param/test06&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">        球队id：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamId&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队位置：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;location&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        创建日期：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;createTime&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;提交&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">    &lt;h3&gt;<span class="number">5</span>、直接使用URL地址传参&lt;/h3&gt;</span><br><span class="line"></span><br><span class="line">    &lt;h3&gt;<span class="number">4</span>、使用HttpServletRequest 对象获取参数&lt;/h3&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/param/test04&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">        球队id：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamId&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队位置：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;location&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;提交&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">    &lt;h3&gt;<span class="number">3</span>、请求参数和方法名称的参数不一致&lt;/h3&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/param/test03&quot;</span> method=<span class="string">&quot;get&quot;</span>&gt;</span><br><span class="line">        球队ID：&lt;input name=<span class="string">&quot;id&quot;</span> /&gt;&lt;br/&gt;</span><br><span class="line">        球队name：&lt;input name=<span class="string">&quot;name&quot;</span> /&gt;&lt;br/&gt;</span><br><span class="line">        球队location：&lt;input name=<span class="string">&quot;location&quot;</span> /&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;提交&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">    &lt;h3&gt;<span class="number">2</span>、使用对象接收多个参数&lt;/h3&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/param/test02&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">        球队id：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamId&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队位置：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;location&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;提交&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">    &lt;h3&gt;<span class="number">1</span>、直接使用方法的参数逐个接收&lt;/h3&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/param/test01&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">        球队id：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamId&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队名称：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        球队位置：&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamLocation&quot;</span>/&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;提交&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>控制器ParamController.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"><span class="keyword">import</span> com.lina.pojo.Team;</span><br><span class="line"><span class="keyword">import</span> com.lina.vo.QueryVO;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.PathVariable;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestParam;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;param&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ParamController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//8、获取集合类型的参数: 简单类型的可以通过@RequestParam注解实现；对象集合不支持直接获取，必须封装在类中，作为一个属性操作</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test08&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test08</span><span class="params">(<span class="meta">@RequestParam(&quot;teamName&quot;)</span> List&lt;String&gt; nameList)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test08-----------------&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (String s : nameList) &#123;</span><br><span class="line">            System.out.println(s);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test09&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test09</span><span class="params">(QueryVO vo)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test09-----------------&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (Team team : vo.getTeamList()) &#123;</span><br><span class="line">            System.out.println(team);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//7、获取数组类型的参数</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test07&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test07</span><span class="params">(String[] teamName,HttpServletRequest request)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test07-----------------&quot;</span>);</span><br><span class="line">        <span class="comment">//方式1：</span></span><br><span class="line">        <span class="keyword">for</span> (String s : teamName) &#123;</span><br><span class="line">            System.out.println(s);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">&quot;---------------&quot;</span>);</span><br><span class="line">        <span class="comment">//方式2：</span></span><br><span class="line">        String[] teamNames = request.getParameterValues(<span class="string">&quot;teamName&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (String name : teamNames) &#123;</span><br><span class="line">            System.out.println(name);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//6、获取日期类型的参数</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test06&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test06</span><span class="params">(Team team)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test06-----------------&quot;</span>);</span><br><span class="line">        System.out.println(team);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//5、直接使用URL地址传参: 借助@PathVariable 注解</span></span><br><span class="line">    <span class="comment">// 例如http://localhost:8080/param/test05/1001/lacker/las</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test05/&#123;id&#125;/&#123;name&#125;/&#123;loc&#125;&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test05</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span> Integer teamId,</span></span><br><span class="line"><span class="params">                               <span class="meta">@PathVariable(&quot;name&quot;)</span> String teamName,</span></span><br><span class="line"><span class="params">                               <span class="meta">@PathVariable(&quot;loc&quot;)</span> String teamLocation)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test05-----------------&quot;</span>);</span><br><span class="line">        System.out.println(teamId);</span><br><span class="line">        System.out.println(teamName);</span><br><span class="line">        System.out.println(teamLocation);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//4、使用HttpServletRequest 对象获取参数：跟原来的javaWeb项目中使用的方式是一样的</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test04&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test04</span><span class="params">(HttpServletRequest request)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test04-----------------&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">teamId</span> <span class="operator">=</span> request.getParameter(<span class="string">&quot;teamId&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">teamName</span> <span class="operator">=</span> request.getParameter(<span class="string">&quot;teamName&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">location</span> <span class="operator">=</span> request.getParameter(<span class="string">&quot;location&quot;</span>);</span><br><span class="line">        <span class="keyword">if</span>(teamId!=<span class="literal">null</span>)</span><br><span class="line">            System.out.println(Integer.valueOf(teamId));</span><br><span class="line">        System.out.println(teamName);</span><br><span class="line">        System.out.println(location);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//3、请求参数和方法名称的参数不一致:使用@RequestParam进行矫正，</span></span><br><span class="line">    <span class="comment">// value属性表示请求中的参数名称</span></span><br><span class="line">    <span class="comment">// required属性表示参数是否是必须的：true:必须赋值，否则报出400错；false：可以不赋值，结果就是null</span></span><br><span class="line">    <span class="comment">//defaultValue=自定义默认值  如果没有从用户请求中获取到值，使用默认值</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test03&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test03</span><span class="params">(<span class="meta">@RequestParam(value = &quot;id&quot;,required = false,defaultValue = &quot;1&quot;)</span> Integer teamId,</span></span><br><span class="line"><span class="params">                               <span class="meta">@RequestParam(value = &quot;name&quot;)</span> String teamName,</span></span><br><span class="line"><span class="params">                               <span class="meta">@RequestParam(value = &quot;location&quot;)</span> String teamLocation)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test03--------------&quot;</span>);</span><br><span class="line">        System.out.println(teamId);</span><br><span class="line">        System.out.println(teamName);</span><br><span class="line">        System.out.println(teamLocation);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;OK&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//2、使用对象接收多个参数：要求用户请求中携带的参数名称必须是实体类中的属性保持一致，否则就获取不到</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test02&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test02</span><span class="params">(Team team)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test02-----------------&quot;</span>);</span><br><span class="line">        System.out.println(team);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 1、直接使用方法的参数逐个接收:方法的参数名称必须与用户请求中携带的参数名称保持一致，否则就获取不到</span></span><br><span class="line"><span class="comment">     * 好处：不需要类型转换</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test01&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test01</span><span class="params">(Integer teamId,String teamName,String teamLocation)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test01-----------------&quot;</span>);</span><br><span class="line">        System.out.println(teamId);</span><br><span class="line">        System.out.println(teamName);</span><br><span class="line">        System.out.println(teamLocation);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;ok&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;hello&quot;)</span></span><br><span class="line">    <span class="keyword">public</span>  ModelAndView <span class="title function_">hello</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ModelAndView</span>(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="7、请求参数中文乱码"><a href="#7、请求参数中文乱码" class="headerlink" title="7、请求参数中文乱码"></a>7、请求参数中文乱码</h1><p>对于前面所接收的请求参数，若含有中文，则会出现中文乱码问题。Spring 对于请求参数中的中文乱码问题，给出了专门的字符集过滤器CharacterEncodingFilter 类。如图所示。</p>
<p><img src="/img%5Cimage-20210324170104000.png" class="lazyload" data-srcset="/img%5Cimage-20210324170104000.png" srcset="" alt="image-20210324170104000"></p>
<h2 id="7-1-乱码解决方案"><a href="#7-1-乱码解决方案" class="headerlink" title="7.1 乱码解决方案"></a>7.1 乱码解决方案</h2><p>在 web.xml 中注册字符集过滤器，推荐将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的。</p>
<p>在web.xml配置文件直接注册字符集</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--注册字符集过滤器：post请求中文乱码问题的解决方案--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>characterEncodingFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-class</span>&gt;</span>org.springframework.web.filter.CharacterEncodingFilter<span class="tag">&lt;/<span class="name">filter-class</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--指定字符集--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>encoding<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--强制request使用字符集encoding--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>forceRequestEncoding<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>true<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--强制response使用字符集encoding--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>forceResponseEncoding<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>true<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">filter</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>characterEncodingFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/*<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">filter-mapping</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="7-2-解决方案原理"><a href="#7-2-解决方案原理" class="headerlink" title="7.2 解决方案原理"></a>7.2 解决方案原理</h2><p><img src="/img%5Cimage-20210324172025218.png" class="lazyload" data-srcset="/img%5Cimage-20210324172025218.png" srcset="" alt="image-20210324172025218"></p>
<h1 id="8、处理器方法的返回值"><a href="#8、处理器方法的返回值" class="headerlink" title="8、处理器方法的返回值"></a>8、处理器方法的返回值</h1><p>使用@Controller 注解的处理器的处理器方法，其返回值常用的有四种类型：</p>
<ol>
<li>ModelAndView</li>
<li>String</li>
<li>返回自定义类型对象</li>
<li>无返回值 void</li>
</ol>
<p>咱们根据实际的业务选择不同的返回值。</p>
<p>案例准备工作：</p>
<p>创建控制器ResultController.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"><span class="keyword">import</span> com.lina.pojo.Team;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;result&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ResultController</span> &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在jsp文件夹中添加页面result.jsp</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;result&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;h1&gt;result----------------&lt;/h1&gt;</span><br><span class="line"></span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<h2 id="8-1-返回ModelAndView"><a href="#8-1-返回ModelAndView" class="headerlink" title="8.1 返回ModelAndView"></a>8.1 返回ModelAndView</h2><p>如果是前后端不分的开发，大部分情况下，我们返回 ModelAndView，即数据模型+视图：</p>
<p>控制器ResultController.java中添加方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//1、返回值是ModelAndView： 这种方式既有数据的携带还有资源的跳转，可以选择该种方式</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test01&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test01</span><span class="params">()</span>&#123;</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();<span class="comment">//模型与视图</span></span><br><span class="line">        <span class="comment">//携带数据</span></span><br><span class="line">        mv.addObject(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;湖人队&quot;</span>);<span class="comment">//相当于request。setAttribute(&quot;teamName&quot;,&quot;湖人队“);</span></span><br><span class="line">        mv.setViewName(<span class="string">&quot;result&quot;</span>);<span class="comment">// 经过视图解析器InternalResourceViewResolver的处理，将逻辑视图名称加上前后缀变为物理资源路径  /jsp/result.jsp</span></span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>Model 中，放我们的数据，然后在 ModelAndView 中指定视图名称。</p>
<p>当处理器方法处理完后，需要跳转到其它资源的同时传递数据，选择返回 ModelAndView 比较好，但是如果只是需要传递数据或者跳转之一，这个时候ModelAndView 就不是最优选择。</p>
<p>result.jsp页面中添加如下内容：</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;h3&gt;test01------$&#123;teamName&#125;---&lt;/h3&gt;</span><br></pre></td></tr></table></figure>

<p><img src="/img%5Cimage-20210327133617946.png" class="lazyload" data-srcset="/img%5Cimage-20210327133617946.png" srcset="" alt="image-20210327133617946"></p>
<h2 id="8-2-返回String"><a href="#8-2-返回String" class="headerlink" title="8.2 返回String"></a>8.2 返回String</h2><p>上一种方式中的 ModelAndView 可以拆分为两部分，Model 和 View，在 SpringMVC 中，Model 我们可以直接在参数中指定，然后<strong>返回值是逻辑视图名</strong>，视图解析器解析可以将逻辑视图名称转换为物理视图地址。</p>
<p><img src="/img%5Cimage-20210324194533583.png" class="lazyload" data-srcset="/img%5Cimage-20210324194533583.png" srcset="" alt="image-20210324194533583"></p>
<p>视图解析器通过<strong>内部资源视图解析器InternalResourceViewResolver</strong>将字符串与解析器中的prefix和suffix结合形成要跳转的额URI。</p>
<p>控制器ResultController.java中添加方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//2、返回字符串</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;test02&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">test02</span><span class="params">(HttpServletRequest request)</span>&#123;</span><br><span class="line">    Team team=<span class="keyword">new</span> <span class="title class_">Team</span>();</span><br><span class="line">    team.setLocation(<span class="string">&quot;迈阿密&quot;</span>);</span><br><span class="line">    team.setTeamId(<span class="number">1002</span>);</span><br><span class="line">    team.setTeamName(<span class="string">&quot;热火&quot;</span>);</span><br><span class="line">    <span class="comment">//携带数据</span></span><br><span class="line">    request.setAttribute(<span class="string">&quot;team&quot;</span>,team);</span><br><span class="line">    request.getSession().setAttribute(<span class="string">&quot;team&quot;</span>,team);</span><br><span class="line">    <span class="comment">//资源的跳转</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;result&quot;</span>;<span class="comment">// 经过视图解析器InternalResourceViewResolver的处理，将逻辑视图名称加上前后缀变为物理资源路径  /jsp/result.jsp</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>result.jsp页面中添加如下内容：</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;h3&gt;test02---request作用域获取:---$&#123;requestScope.team.teamName&#125;---$&#123;requestScope.team.teamId&#125;---$&#123;requestScope.team.location&#125;&lt;/h3&gt;</span><br><span class="line">&lt;h3&gt;test02---session作用域获取:---$&#123;sessionScope.team.teamName&#125;---$&#123;sessionScope.team.teamId&#125;---$&#123;sessionScope.team.location&#125;&lt;/h3&gt;</span><br></pre></td></tr></table></figure>

<p><img src="/img%5Cimage-20210327133734491.png" class="lazyload" data-srcset="/img%5Cimage-20210327133734491.png" srcset="" alt="image-20210327133734491"></p>
<h2 id="8-3-返回对象类型"><a href="#8-3-返回对象类型" class="headerlink" title="8.3 返回对象类型"></a>8.3 返回对象类型</h2><p>当处理器方法返回Object对象类型的时候，可以是Integer、String、Map、List，也可以是自定义的对象类型。但是无论是什么类型，都不是作为逻辑视图出现，而是直接作为数据返回然后展示的。一般前端发起Ajax请求的时候都会使用直接返回对象的形式。</p>
<p>返回对象的时候，需要使用@ResponseBody 注解，将转换后的 JSON 数据放入到响应体中。</p>
<p>pom.xml文件中添加两个依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.fasterxml.jackson.core<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jackson-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.9.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.fasterxml.jackson.core<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jackson-databind<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.9.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="8-3-1-返回基础类型"><a href="#8-3-1-返回基础类型" class="headerlink" title="8.3.1 返回基础类型"></a>8.3.1 返回基础类型</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//3、返回对象类型：Integer Double String  自定义类型   List  Map  返回的不是逻辑视图的名称，而直接就是数据返回 ，一般是ajax请求搭配使用 ，将json格式的数据直接返回给响应体</span></span><br><span class="line">   <span class="comment">// 一定要与@ResponseBody</span></span><br><span class="line">   <span class="meta">@ResponseBody</span></span><br><span class="line">   <span class="meta">@RequestMapping(&quot;test03-1&quot;)</span></span><br><span class="line">   <span class="keyword">public</span> Integer <span class="title function_">test031</span><span class="params">()</span>&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="number">666</span>;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="meta">@ResponseBody</span></span><br><span class="line">   <span class="meta">@RequestMapping(&quot;test03-2&quot;)</span></span><br><span class="line">   <span class="keyword">public</span> String <span class="title function_">test032</span><span class="params">()</span>&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="string">&quot;test&quot;</span>;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<h3 id="8-3-2-返回自定义对象类型"><a href="#8-3-2-返回自定义对象类型" class="headerlink" title="8.3.2 返回自定义对象类型"></a>8.3.2 返回自定义对象类型</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ResponseBody</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test03-3&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Team <span class="title function_">test033</span><span class="params">()</span>&#123;</span><br><span class="line">        Team team=<span class="keyword">new</span> <span class="title class_">Team</span>();</span><br><span class="line">        team.setLocation(<span class="string">&quot;迈阿密&quot;</span>);</span><br><span class="line">        team.setTeamId(<span class="number">1002</span>);</span><br><span class="line">        team.setTeamName(<span class="string">&quot;热火&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> team;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;div&gt;</span><br><span class="line">    &lt;button type=<span class="string">&quot;button&quot;</span> id=<span class="string">&quot;btn1&quot;</span>&gt;ajax请求自定义对象&lt;/button&gt;</span><br><span class="line">    &lt;h3&gt;ajax请求自定义对象的结果展示&lt;/h3&gt;</span><br><span class="line">    &lt;p id=<span class="string">&quot;res&quot;</span>&gt;&lt;/p&gt;</span><br><span class="line">&lt;/div&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">    $(function()&#123;</span><br><span class="line">        $(<span class="string">&quot;#btn1&quot;</span>).click(function () &#123;</span><br><span class="line">            $.ajax(&#123;</span><br><span class="line">                type: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">                url: <span class="string">&quot;/result/test03-3&quot;</span>,</span><br><span class="line">                data: <span class="string">&quot;&quot;</span>,</span><br><span class="line">                success: function(msg)&#123;</span><br><span class="line">                    alert( <span class="string">&quot;Data Saved: &quot;</span> + msg );</span><br><span class="line">                     <span class="keyword">var</span> name=msg.teamName;</span><br><span class="line">                     <span class="keyword">var</span> id=msg.teamId;</span><br><span class="line">                     <span class="keyword">var</span> loc=msg.location;</span><br><span class="line">                    $(<span class="string">&quot;#res&quot;</span>).html(<span class="string">&quot;name:&quot;</span>+name+<span class="string">&quot;,id:&quot;</span>+id+<span class="string">&quot;,location:&quot;</span>+loc);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p><img src="/img%5Cimage-20210327155438988.png" class="lazyload" data-srcset="/img%5Cimage-20210327155438988.png" srcset="" alt="image-20210327155438988"></p>
<h3 id="8-3-3-返回集合List"><a href="#8-3-3-返回集合List" class="headerlink" title="8.3.3 返回集合List"></a>8.3.3 返回集合List</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ResponseBody</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test03-4&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Team&gt; <span class="title function_">test034</span><span class="params">()</span>&#123;</span><br><span class="line">        List&lt;Team&gt; list=<span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;(<span class="number">5</span>);</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=<span class="number">5</span>;i++) &#123;</span><br><span class="line">            <span class="type">Team</span> <span class="variable">team</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Team</span>();</span><br><span class="line">            team.setLocation(<span class="string">&quot;迈阿密&quot;</span>+i);</span><br><span class="line">            team.setTeamId(<span class="number">1002</span>+i);</span><br><span class="line">            team.setTeamName(<span class="string">&quot;热火&quot;</span>+i);</span><br><span class="line">            list.add(team);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">&lt;div&gt;</span><br><span class="line">       &lt;button type=<span class="string">&quot;button&quot;</span> id=<span class="string">&quot;btn2&quot;</span>&gt;ajax请求对象--List&lt;/button&gt;</span><br><span class="line">       &lt;h3&gt;ajax请求自定义对象--list的结果展示&lt;/h3&gt;</span><br><span class="line">       &lt;p id=<span class="string">&quot;res2&quot;</span>&gt;&lt;/p&gt;</span><br><span class="line">   &lt;/div&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">    $(function()&#123;</span><br><span class="line">        $(<span class="string">&quot;#btn2&quot;</span>).click(</span><br><span class="line">            function()&#123;</span><br><span class="line">                $.ajax(&#123;</span><br><span class="line">                    type:<span class="string">&quot;POST&quot;</span>,</span><br><span class="line">                    url:<span class="string">&quot;/result/test03-4&quot;</span>,</span><br><span class="line">                    data:<span class="string">&quot;&quot;</span>,</span><br><span class="line">                    success:function (list) &#123;</span><br><span class="line">                        <span class="comment">//alert(msg);</span></span><br><span class="line">                        <span class="type">var</span> <span class="variable">str</span> <span class="operator">=</span> <span class="string">&quot;&quot;</span>;</span><br><span class="line">                        <span class="keyword">for</span> (<span class="type">var</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; list.length; i++) &#123;</span><br><span class="line">                            <span class="keyword">var</span> msg=list[i];</span><br><span class="line">                            <span class="type">var</span> <span class="variable">name</span> <span class="operator">=</span> msg.teamName;</span><br><span class="line">                            <span class="type">var</span> <span class="variable">id</span> <span class="operator">=</span> msg.teamId;</span><br><span class="line">                            <span class="type">var</span> <span class="variable">location</span> <span class="operator">=</span> msg.location;</span><br><span class="line">                            str+=<span class="string">&quot;name:&quot;</span> + name + <span class="string">&quot;,id:&quot;</span> + id + <span class="string">&quot;,location:&quot;</span> + location+<span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line">                        &#125;</span><br><span class="line">                        $(<span class="string">&quot;#res2&quot;</span>).html(str);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;);</span><br><span class="line">            &#125;</span><br><span class="line">        );</span><br><span class="line">    &#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p><img src="/img%5Cimage-20210327155458475.png" class="lazyload" data-srcset="/img%5Cimage-20210327155458475.png" srcset="" alt="image-20210327155621149"></p>
<h3 id="8-3-4-返回集合Map"><a href="#8-3-4-返回集合Map" class="headerlink" title="8.3.4 返回集合Map"></a>8.3.4 返回集合Map</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ResponseBody</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test03-5&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Map&lt;String,Team&gt; <span class="title function_">test035</span><span class="params">()</span>&#123;</span><br><span class="line">        Map&lt;String,Team&gt; map=<span class="keyword">new</span> <span class="title class_">HashMap</span>();</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=<span class="number">5</span>;i++) &#123;</span><br><span class="line">            <span class="type">Team</span> <span class="variable">team</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Team</span>();</span><br><span class="line">            team.setLocation(<span class="string">&quot;金州&quot;</span>+i);</span><br><span class="line">            team.setTeamId(<span class="number">1000</span>+i);</span><br><span class="line">            team.setTeamName(<span class="string">&quot;勇士&quot;</span>+i);</span><br><span class="line">            <span class="comment">//日期类型，在返回的时候是个数字，如果想要按日期格式展示需要在实体类对应属性添加注解@JsonFormat(pattern = &quot;yyyy-MM-dd&quot;)</span></span><br><span class="line">            team.setCreateTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">           map.put(team.getTeamId()+<span class="string">&quot;&quot;</span>,team);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> map;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&lt;div&gt;</span><br><span class="line">       &lt;button type=<span class="string">&quot;button&quot;</span> id=<span class="string">&quot;btn3&quot;</span>&gt;ajax请求对象-Map&lt;/button&gt;</span><br><span class="line">       &lt;h3&gt;ajax请求对象--Map的结果展示&lt;/h3&gt;</span><br><span class="line">       &lt;p id=<span class="string">&quot;res3&quot;</span>&gt;&lt;/p&gt;</span><br><span class="line">   &lt;/div&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">	$(function()&#123;</span><br><span class="line">        $(<span class="string">&quot;#btn3&quot;</span>).click(function () &#123;</span><br><span class="line">            $.ajax(&#123;</span><br><span class="line">                type: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">                url: <span class="string">&quot;/result/test03-5&quot;</span>,</span><br><span class="line">                data: <span class="string">&quot;&quot;</span>,</span><br><span class="line">                success: function(map)&#123;</span><br><span class="line">                    alert( <span class="string">&quot;Data Saved: &quot;</span> + map );</span><br><span class="line">                    <span class="keyword">var</span> str=<span class="string">&quot;&quot;</span>;</span><br><span class="line">                    $.each(map,function (i,obj) &#123;</span><br><span class="line">                        str+=<span class="string">&quot;name:&quot;</span>+obj.teamName+<span class="string">&quot;,id:&quot;</span>+obj.teamId+<span class="string">&quot;,location:&quot;</span>+obj.location+<span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line">                    &#125;);</span><br><span class="line">                    $(<span class="string">&quot;#res3&quot;</span>).html(str);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p><img src="/img%5Cimage-20210327155522148.png" class="lazyload" data-srcset="/img%5Cimage-20210327155522148.png" srcset="" alt="image-20210327155522148"></p>
<h2 id="8-4-无返回值-void-了解"><a href="#8-4-无返回值-void-了解" class="headerlink" title="8.4 无返回值 void-了解"></a>8.4 无返回值 void-了解</h2><p>方法的返回值为 void，并不一定真的没有返回值，我们可以通过其他方式给前端返回。实际上，这种方式也可以理解为 Servlet 中的的处理方案。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//通过 HttpServletRequest 做服务端跳转</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;test04-1&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test041</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;直接使用HttpServletRequest进行服务器端的转发&quot;</span>);</span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;/jsp/ok.jsp&quot;</span>).forward(request,response);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//通过 HttpServletResponse 做重定向</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;test04-2&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test042</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;直接使用HttpServletResponse重定向跳转&quot;</span>);</span><br><span class="line">        response.sendRedirect(<span class="string">&quot;/jsp/ok.jsp&quot;</span>);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//通过 HttpServletResponse 给出响应</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;test04-3&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test043</span><span class="params">(HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        response.setCharacterEncoding(<span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line">        response.setContentType(<span class="string">&quot;text/html;charset=UTF-8&quot;</span>);</span><br><span class="line">        <span class="type">PrintWriter</span> <span class="variable">writer</span> <span class="operator">=</span> response.getWriter();</span><br><span class="line">        writer.write(<span class="string">&quot;返回void类型测试---直接返回字符串&quot;</span>);</span><br><span class="line">        writer.flush();</span><br><span class="line">        writer.close();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//也可以自己手动指定响应头去实现重定向：</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;test04-4&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test044</span><span class="params">(HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        response.setStatus(<span class="number">302</span>);<span class="comment">//设置响应码，302表示重定向</span></span><br><span class="line">       response.setHeader(<span class="string">&quot;Location&quot;</span>,<span class="string">&quot;/jsp/ok.jsp&quot;</span>);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h1 id="9、页面导航-资源跳转的方式"><a href="#9、页面导航-资源跳转的方式" class="headerlink" title="9、页面导航&#x2F;资源跳转的方式"></a>9、页面导航&#x2F;资源跳转的方式</h1><p>页面导航分为两种：1、转发   2、重定向</p>
<p>springMVC有以下两种方式实现页面的转发或重定向：</p>
<p>1、返回字符串</p>
<p>2、使用ModelAndView</p>
<p>在SpringMVC中两种导航进行页面导航的时候使用不同的前缀指定转发还是重定向</p>
<p>前缀：  转发：    forward:url  默认</p>
<p>​			 重定向：  redirect:url</p>
<p>准备工作：创建一个新的控制器NavigationController.java：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: NavigationController</span></span><br><span class="line"><span class="comment"> * SpringMVC导航的方式</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;navigation&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NavigationController</span> &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="9-1-转发到一个jsp页面"><a href="#9-1-转发到一个jsp页面" class="headerlink" title="9.1 转发到一个jsp页面"></a>9.1 转发到一个jsp页面</h2><h3 id="9-1-1-字符串方式转发"><a href="#9-1-1-字符串方式转发" class="headerlink" title="9.1.1 字符串方式转发"></a>9.1.1 字符串方式转发</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;test01-1&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">test011</span><span class="params">(HttpServletRequest request)</span>&#123;</span><br><span class="line">        request.setAttribute(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;湖人&quot;</span>);</span><br><span class="line">        <span class="comment">//return &quot;OK&quot;;//默认方式:由视图解析器处理之后将逻辑视图转为物理资源路径</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;forward:/jsp/OK.jsp&quot;</span>;<span class="comment">//当添加了forward前缀之后，视图解析器中的前后缀就失效了，必须自己编写绝对路径</span></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h3 id="9-1-2-ModelAndView转发"><a href="#9-1-2-ModelAndView转发" class="headerlink" title="9.1.2 ModelAndView转发"></a>9.1.2 ModelAndView转发</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;test01-2&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test012</span><span class="params">()</span>&#123;</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.addObject(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;热火&quot;</span>);</span><br><span class="line">        <span class="comment">//mv.setViewName(&quot;OK&quot;);//默认方式:由视图解析器处理之后将逻辑视图转为物理资源路径</span></span><br><span class="line">        mv.setViewName( <span class="string">&quot;forward:/jsp/OK.jsp&quot;</span>);<span class="comment">//当添加了forward前缀之后，视图解析器中的前后缀就失效了，必须自己编写绝对路径</span></span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h2 id="9-2-重定向到一个jsp页面"><a href="#9-2-重定向到一个jsp页面" class="headerlink" title="9.2 重定向到一个jsp页面"></a>9.2 重定向到一个jsp页面</h2><h3 id="9-2-1-字符串方式重定向"><a href="#9-2-1-字符串方式重定向" class="headerlink" title="9.2.1 字符串方式重定向"></a>9.2.1 字符串方式重定向</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;test02-1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">test021</span><span class="params">(HttpServletRequest request)</span>&#123;</span><br><span class="line">    request.setAttribute(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;勇士&quot;</span>);<span class="comment">//页面上无法获取到存储在request作用域中的值，请求中断了</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;redirect:/jsp/OK.jsp&quot;</span>;<span class="comment">//当添加了redirect前缀之后，视图解析器中的前后缀就失效了，必须自己编写绝对路径</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="9-2-2-ModelAndView重定向方式"><a href="#9-2-2-ModelAndView重定向方式" class="headerlink" title="9.2.2 ModelAndView重定向方式"></a>9.2.2 ModelAndView重定向方式</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;test02-2&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test022</span><span class="params">(HttpServletRequest request)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test02-2--------------&quot;</span>);</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        <span class="comment">//存储在request作用域中的值以参数的形式追加在URL后面  http://localhost:8080/jsp/OK.jsp?teamName=热火队&amp;teamId=1001</span></span><br><span class="line">        mv.addObject(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;热火队&quot;</span>);</span><br><span class="line">        mv.addObject(<span class="string">&quot;teamId&quot;</span>,<span class="string">&quot;1001&quot;</span>);</span><br><span class="line">        mv.setViewName(<span class="string">&quot;redirect:/jsp/OK.jsp&quot;</span>);<span class="comment">//当添加了redirect前缀之后，视图解析器中的前后缀就失效了，必须自己编写绝对路径</span></span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h2 id="9-3-重定向或者转发到控制器"><a href="#9-3-重定向或者转发到控制器" class="headerlink" title="9.3 重定向或者转发到控制器"></a>9.3 重定向或者转发到控制器</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//重定向或者转发到控制器</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test03-1&quot;)</span></span><br><span class="line">   <span class="keyword">public</span> ModelAndView <span class="title function_">test031</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test03-1----转发到控制&quot;</span>);</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.addObject(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;小牛&quot;</span>);</span><br><span class="line">        mv.setViewName(<span class="string">&quot;forward:/navigation/test02-2&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test03-2&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test032</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;test03-2----重定向到控制&quot;</span>);</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.addObject(<span class="string">&quot;teamName&quot;</span>,<span class="string">&quot;凯尔特人&quot;</span>);</span><br><span class="line">        mv.addObject(<span class="string">&quot;teadmId&quot;</span>,<span class="string">&quot;1003&quot;</span>);</span><br><span class="line">        mv.setViewName(<span class="string">&quot;redirect:/navigation/test01-1&quot;</span>);<span class="comment">//参数值直接追加到URL后面</span></span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h1 id="10、异常处理"><a href="#10、异常处理" class="headerlink" title="10、异常处理"></a>10、异常处理</h1><p>SpringMVC框架常用@ExceptionHandler 注解处理异常。</p>
<h2 id="10-1-ExceptionHandler-注解"><a href="#10-1-ExceptionHandler-注解" class="headerlink" title="10.1@ExceptionHandler 注解"></a>10.1@ExceptionHandler 注解</h2><p>@ExceptionHandler 可以将一个方法指定为异常处理方法。</p>
<p>被注解的方法，其返回值可以是 ModelAndView、String，或 void，方法名随意，方法参数可以是 Exception 及其子类对象、HttpServletRequest、HttpServletResponse 等。系统会自动为这些方法参数赋值。</p>
<p>对于异常处理注解的用法，也可以直接将异常处理方法注解于 Controller 之中.</p>
<p><img src="/img%5Cimage-20210325160516050.png" class="lazyload" data-srcset="/img%5Cimage-20210325160516050.png" srcset="" alt="image-20210325160516050"></p>
<h2 id="10-2-实现步骤"><a href="#10-2-实现步骤" class="headerlink" title="10.2 实现步骤"></a>10.2 实现步骤</h2><h3 id="10-2-1-自定义异常类"><a href="#10-2-1-自定义异常类" class="headerlink" title="10.2.1 自定义异常类"></a>10.2.1 自定义异常类</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.exceptions;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: TeamException</span></span><br><span class="line"><span class="comment"> * 自定义的异常类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeamException</span> <span class="keyword">extends</span> <span class="title class_">Exception</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">TeamException</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">TeamException</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.exceptions;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: TeamIdException</span></span><br><span class="line"><span class="comment"> *自定义的异常类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeamIDException</span> <span class="keyword">extends</span> <span class="title class_">TeamException</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">TeamIDException</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">TeamIDException</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.exceptions;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: TeamException</span></span><br><span class="line"><span class="comment"> * 自定义的异常类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TeamNameException</span> <span class="keyword">extends</span>  <span class="title class_">TeamException</span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">TeamNameException</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">TeamNameException</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>编写控制器</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"><span class="keyword">import</span> com.lina.exceptions.TeamException;</span><br><span class="line"><span class="keyword">import</span> com.lina.exceptions.TeamIdException;</span><br><span class="line"><span class="keyword">import</span> com.lina.exceptions.TeamNameException;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.ExceptionHandler;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.PathVariable;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: ExController</span></span><br><span class="line"><span class="comment"> * 测试异常处理的控制器</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;ex&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ExController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;test01/&#123;id&#125;/&#123;name&#125;/&#123;loc&#125;&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">test01</span><span class="params">(</span></span><br><span class="line"><span class="params">            <span class="meta">@PathVariable(&quot;id&quot;)</span> Integer teamId,</span></span><br><span class="line"><span class="params">            <span class="meta">@PathVariable(&quot;name&quot;)</span>String teamName,</span></span><br><span class="line"><span class="params">            <span class="meta">@PathVariable(&quot;loc&quot;)</span>String loc)</span> <span class="keyword">throws</span> TeamException &#123;</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        <span class="keyword">if</span>(teamId&lt;=<span class="number">1000</span>)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TeamIDException</span>(<span class="string">&quot;teamId不合法！必须在1000之上！&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(<span class="string">&quot;test&quot;</span>.equalsIgnoreCase(teamName))&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TeamNameException</span>(<span class="string">&quot;teamName不合法！不能使用test&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(<span class="string">&quot;test&quot;</span>.equalsIgnoreCase(loc))&#123;</span><br><span class="line">            <span class="keyword">throw</span>  <span class="keyword">new</span> <span class="title class_">TeamException</span>(<span class="string">&quot;team出现了异常！&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//System.out.println(10/0);</span></span><br><span class="line">        mv.setViewName(<span class="string">&quot;OK&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ExceptionHandler(value = &#123;TeamIdException.class,TeamNameException.class,Exception.class&#125;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">exHandler</span><span class="params">(Exception ex)</span>&#123;</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.addObject(<span class="string">&quot;msg&quot;</span>,ex.getMessage());</span><br><span class="line">        <span class="keyword">if</span>(ex <span class="keyword">instanceof</span> TeamIdException)</span><br><span class="line">             mv.setViewName(<span class="string">&quot;idError&quot;</span>);</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span>(ex <span class="keyword">instanceof</span> TeamNameException)</span><br><span class="line">            mv.setViewName(<span class="string">&quot;nameError&quot;</span>);</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            mv.setViewName(<span class="string">&quot;error&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>编写error.jsp、idError.jsp、nameError.jsp页面</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;error&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;h1&gt;默认的错误页面--$&#123;msg&#125;&lt;/h1&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;id error&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;h1&gt;teamId Error----$&#123;msg&#125;&lt;/h1&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;name error&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;h1&gt;teamName error---$&#123;msg&#125;&lt;/h1&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>测试：</p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/ex/test01/100/test1">http://localhost:8080/ex/test01/100/test1</a></p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/ex/test01/1004/test">http://localhost:8080/ex/test01/1004/test</a></p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/ex/test01/1001/test1">http://localhost:8080/ex/test01/1001/test1</a></p>
<h2 id="10-3优化"><a href="#10-3优化" class="headerlink" title="10.3优化"></a>10.3优化</h2><p>一般将异常处理方法专门定义在一个类中，作为全局的异常处理类。</p>
<p>使用注解@ControllerAdvice，就是“控制器增强”，是给控制器对象增强功能的。使用@ControllerAdvice 修饰的类中可以使用@ExceptionHandler。</p>
<p>当使用@RequestMapping 注解修饰的方法抛出异常时，会执行@ControllerAdvice 修饰的类中的异常处理方法。</p>
<p>@ControllerAdvice 注解所在的类需要进行包扫描，否则无法创建对象。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.lina.exceptions&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>定义全局异常处理类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.exceptions;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.ControllerAdvice;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.ExceptionHandler;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 自定义的全局的异常处理类</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@ControllerAdvice</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GlobalException</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ExceptionHandler(value = &#123;TeamIDException.class&#125;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">exHandler1</span><span class="params">(Exception ex)</span>&#123;</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">            mv.setViewName(<span class="string">&quot;idError&quot;</span>);</span><br><span class="line">        mv.addObject(<span class="string">&quot;msg&quot;</span>,ex.getMessage());</span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@ExceptionHandler(value = &#123;TeamNameException.class&#125;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">exHandler2</span><span class="params">(Exception ex)</span>&#123;</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">            mv.setViewName(<span class="string">&quot;nameError&quot;</span>);</span><br><span class="line">        mv.addObject(<span class="string">&quot;msg&quot;</span>,ex.getMessage());</span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@ExceptionHandler(value =&#123;TeamException.class&#125;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">exHandler3</span><span class="params">(Exception ex)</span>&#123;</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">            mv.setViewName(<span class="string">&quot;error&quot;</span>);</span><br><span class="line">        mv.addObject(<span class="string">&quot;msg&quot;</span>,ex.getMessage());</span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@ExceptionHandler(value =&#123;Exception.class&#125;)</span></span><br><span class="line">    <span class="keyword">public</span> ModelAndView <span class="title function_">exHandler4</span><span class="params">(Exception ex)</span>&#123;</span><br><span class="line">        ModelAndView mv=<span class="keyword">new</span> <span class="title class_">ModelAndView</span>();</span><br><span class="line">        mv.setViewName(<span class="string">&quot;error&quot;</span>);</span><br><span class="line">        mv.addObject(<span class="string">&quot;msg&quot;</span>,ex.getMessage());</span><br><span class="line">        <span class="keyword">return</span> mv;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h1 id="11、拦截器"><a href="#11、拦截器" class="headerlink" title="11、拦截器"></a>11、拦截器</h1><p>SpringMVC 中的 拦截器（ Interceptor）是非常重要的，它的主要作用是拦截指定的用户请求，并进行相应的预处理与后处理。</p>
<p>拦截的时间点在“处理器映射器HandlerMapping根据用户提交的请求映射出了所要执行的处理器类，并且也找到了要执行该处理器类的处理器适配器，在处理器适配器HandlerAdaptor执行处理器之前”。</p>
<p>在处理器映射器映射出所要执行的处理器类时，已经将拦截器与处理器组合为了一个处理器执行链HandlerExecutionChain，并返回给了前端控制器。</p>
<p>自定义拦截器，需要实现 HandlerInterceptor 接口。而该接口中含有三个方法：</p>
<p><img src="/img%5Cimage-20210325161053558.png" class="lazyload" data-srcset="/img%5Cimage-20210325161053558.png" srcset="" alt="image-20210325161053558"></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">preHandle(request,response, Object handler)：</span><br><span class="line">	该方法在处理器方法执行之前执行。其返回值为boolean，若为true，则紧接着会执行处理器方法，且会将afterCompletion()方法放入到一个专门的方法栈中等待执行。</span><br><span class="line"></span><br><span class="line">postHandle(request,response, Object handler,modelAndView)：</span><br><span class="line">	该方法在处理器方法执行之后执行。处理器方法若最终未被执行，则该方法不会执行。由于该方法是在处理器方法执行完后执行，且该方法参数中包含 ModelAndView，所以该方法可以修改处理器方法的处理结果数据，且可以修改跳转方向。</span><br><span class="line"></span><br><span class="line">afterCompletion(request,response, Object handler, Exception ex)： </span><br><span class="line">	当 preHandle()方法返回true时，会将该方法放到专门的方法栈中，等到对请求进行响应的所工作完成之后才执行该方法。即该方法是在前端控制器渲染（数据填充）了响应页面之后执行的，此时对ModelAndView再操作也对响应无济于事。</span><br><span class="line"></span><br><span class="line">afterCompletion最后执行的方法，清除资源，例如在Controller方法中加入数据</span><br></pre></td></tr></table></figure>

<h2 id="11-1-自定义拦截器"><a href="#11-1-自定义拦截器" class="headerlink" title="11.1 自定义拦截器"></a>11.1 自定义拦截器</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.interceptor;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.HandlerInterceptor;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: MyInterceptor</span></span><br><span class="line"><span class="comment"> * 自定义拦截器</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyInterceptor</span> <span class="keyword">implements</span> <span class="title class_">HandlerInterceptor</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//执行时间： 控制器方法执行之前，在ModelAndView返回之前</span></span><br><span class="line">    <span class="comment">//使用场景: 登录验证</span></span><br><span class="line">    <span class="comment">// 返回值 true : 继续执行控制器方法 表示放行    false: 不会继续执行控制器方法，表示拦截</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">preHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;preHandle-------------------&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//执行时间： 控制器方法执行之hou后，在ModelAndView返回之前，有机会修改返回值</span></span><br><span class="line">    <span class="comment">//使用场景: 日记记录，记录登录的ip,时间</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">postHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;postHandle-------------------&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//执行时间： 控制器方法执行之后，在ModelAndView返回之后，没有机会修改返回值</span></span><br><span class="line">    <span class="comment">//使用场景: 全局资源的一些操作</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterCompletion</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;afterCompletion-------------------&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.interceptor;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.HandlerInterceptor;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.ModelAndView;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: MyInterceptor</span></span><br><span class="line"><span class="comment"> * 自定义拦截器</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyInterceptor2</span> <span class="keyword">implements</span> <span class="title class_">HandlerInterceptor</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//执行时间： 控制器方法执行之前，在ModelAndView返回之前</span></span><br><span class="line">    <span class="comment">//使用场景: 登录验证</span></span><br><span class="line">    <span class="comment">// 返回值 true : 继续执行控制器方法 表示放行    false: 不会继续执行控制器方法，表示拦截</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">preHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;preHandle2-------------------&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//执行时间： 控制器方法执行之hou后，在ModelAndView返回之前，有机会修改返回值</span></span><br><span class="line">    <span class="comment">//使用场景: 日记记录，记录登录的ip,时间</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">postHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;postHandle-2------------------&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//执行时间： 控制器方法执行之后，在ModelAndView返回之后，没有机会修改返回值</span></span><br><span class="line">    <span class="comment">//使用场景: 全局资源的一些操作</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterCompletion</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;afterCompletion2-------------------&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="11-2-配置拦截器"><a href="#11-2-配置拦截器" class="headerlink" title="11.2 配置拦截器"></a>11.2 配置拦截器</h2><p>在springmvc.xml中添加如下配置</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 配置拦截器 --&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">mvc:interceptors</span>&gt;</span></span><br><span class="line">		<span class="comment">&lt;!-- 这里可以同时配置多个拦截器，配置的顺序就是拦截器的拦截顺序 --&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">mvc:interceptor</span>&gt;</span></span><br><span class="line">			<span class="comment">&lt;!-- 拦截器要拦截的请求路径  拦截所有用/** --&gt;</span></span><br><span class="line">			<span class="tag">&lt;<span class="name">mvc:mapping</span> <span class="attr">path</span>=<span class="string">&quot;/**&quot;</span>/&gt;</span></span><br><span class="line">			<span class="comment">&lt;!-- 指定干活的拦截器 --&gt;</span></span><br><span class="line">			 <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;com.lina.interceptor.MyInterceptor2&quot;</span> <span class="attr">id</span>=<span class="string">&quot;myInterceptor&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;/<span class="name">mvc:interceptor</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">mvc:interceptor</span>&gt;</span></span><br><span class="line">			<span class="comment">&lt;!-- 拦截器要拦截的请求路径  拦截所有用/** --&gt;</span></span><br><span class="line">			<span class="tag">&lt;<span class="name">mvc:mapping</span> <span class="attr">path</span>=<span class="string">&quot;/**&quot;</span>/&gt;</span></span><br><span class="line">			<span class="comment">&lt;!-- 指定干活的拦截器 --&gt;</span></span><br><span class="line">			 <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;com.lina.interceptor.MyInterceptor2&quot;</span> <span class="attr">id</span>=<span class="string">&quot;myInterceptor2&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">		<span class="tag">&lt;/<span class="name">mvc:interceptor</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;/<span class="name">mvc:interceptors</span>&gt;</span></span><br><span class="line">    如果有多个拦截器的时候：</span><br><span class="line">preHandle：按照配置前后顺序执行</span><br><span class="line">postHandle：按照配置前后逆序执行</span><br><span class="line">afterCompletion：按照配置前后逆序执行</span><br></pre></td></tr></table></figure>

<h1 id="12、文件上传和下载"><a href="#12、文件上传和下载" class="headerlink" title="12、文件上传和下载"></a>12、文件上传和下载</h1><p>Spring MVC为文件上传提供了直接支持,这种支持是通过即插即用的MultipartResolver实现. </p>
<p>Spring中有一个MultipartResolver的实现类:CommonsMultipartResolver。</p>
<p>在SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下不能处理文件上传工作。</p>
<p>如果想使用Spring的文件上传功能,则需要先在上下文中配置MultipartResolver。</p>
<h2 id="12-1-文件上传"><a href="#12-1-文件上传" class="headerlink" title="12.1 文件上传"></a>12.1 文件上传</h2><p>  （1）添加依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>commons-fileupload<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>commons-fileupload<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.3.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>(2)springmvc.xml文件中配置MultipartResolver:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--文件上传--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;multipartResolver&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.web.multipart.commons.CommonsMultipartResolver&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>（3）fileHandle.jsp页面表单</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;文件操作&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;form action=<span class="string">&quot;/file/upload&quot;</span> method=<span class="string">&quot;post&quot;</span> enctype=<span class="string">&quot;multipart/form-data&quot;</span>&gt;</span><br><span class="line">        请选择文件：&lt;input type=<span class="string">&quot;file&quot;</span> name=<span class="string">&quot;myFile&quot;</span> /&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;上传文件&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>（4）配置java代码(注意要创建文件夹保存上传之后的文件)</p>
<p><img src="/img%5Cimage-20210329123634482.png" class="lazyload" data-srcset="/img%5Cimage-20210329123634482.png" srcset="" alt="image-20210329123634482"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestParam;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.multipart.MultipartFile;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> java.io.File;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.UUID;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: FileController</span></span><br><span class="line"><span class="comment"> * 文件操作的控制器</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;file&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FileController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 文件上传</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> myFile</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> request</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;upload&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">upload</span><span class="params">(<span class="meta">@RequestParam(&quot;myFile&quot;)</span> MultipartFile myFile, HttpServletRequest request)</span>&#123;</span><br><span class="line">        <span class="comment">//获取文件的原始名称 d:\te.aa\txcat.jpg</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">originalFilename</span> <span class="operator">=</span> myFile.getOriginalFilename();</span><br><span class="line">        <span class="comment">// 实际开发中，一般都要将文件重新名称进行存储</span></span><br><span class="line">        <span class="comment">// 存储到服务器的文件名称=随机的字符串+根据实际名称获取到源文件的后缀</span></span><br><span class="line">        String fileName= UUID.randomUUID().toString().replace(<span class="string">&quot;-&quot;</span>,<span class="string">&quot;&quot;</span>) +originalFilename.substring(originalFilename.lastIndexOf(<span class="string">&quot;.&quot;</span>));</span><br><span class="line">        System.out.println(fileName);</span><br><span class="line">        <span class="comment">//文件存储路径</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">realPath</span> <span class="operator">=</span> request.getServletContext().getRealPath(<span class="string">&quot;/uploadFile&quot;</span>)+<span class="string">&quot;/&quot;</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            myFile.transferTo(<span class="keyword">new</span> <span class="title class_">File</span>(realPath+fileName));<span class="comment">//真正的文件上传到服务器指定的位置</span></span><br><span class="line">            System.out.println(<span class="string">&quot;上传成功！&quot;</span>+realPath+fileName);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;OK&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;hello&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">hello</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;fileHandle&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>优化：如果需要限定文件的大小，可以通过配置文件的方式，但是不好捕捉异常。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--配置拦截器--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mvc:interceptors</span>&gt;</span></span><br><span class="line">        ......</span><br><span class="line">        <span class="tag">&lt;<span class="name">mvc:interceptor</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">mvc:mapping</span> <span class="attr">path</span>=<span class="string">&quot;/**&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;com.lina.interceptor.FileInterceptor&quot;</span> <span class="attr">id</span>=<span class="string">&quot;fileInterceptor&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">mvc:interceptor</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">mvc:interceptors</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--文件上传--&gt;</span></span><br><span class="line">   <span class="comment">&lt;!--文件上传的配置--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;multipartResolver&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.web.multipart.commons.CommonsMultipartResolver&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--限定文件上传的大小 以字节B为单位  1024B=1Kb   1024KB=1M  --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--&lt;property name=&quot;maxUploadSize&quot; value=&quot;512000&quot;/&gt;--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;defaultEncoding&quot;</span> <span class="attr">value</span>=<span class="string">&quot;utf-8&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;resolveLazily&quot;</span> <span class="attr">value</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>提供拦截器的方式：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.interceptor;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.multipart.MultipartFile;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.multipart.MultipartHttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.HandlerInterceptor;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"><span class="keyword">import</span> java.util.Iterator;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: FileInterceptor</span></span><br><span class="line"><span class="comment"> * 文件后缀处理的拦截器</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FileInterceptor</span> <span class="keyword">implements</span> <span class="title class_">HandlerInterceptor</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 在文件上传之前判断文件后缀是否合法</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">preHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="comment">//判断是否是文件上传的请求</span></span><br><span class="line">        <span class="type">boolean</span> flag=<span class="literal">true</span>;</span><br><span class="line">        <span class="keyword">if</span>(request <span class="keyword">instanceof</span> MultipartHttpServletRequest)&#123;</span><br><span class="line">            MultipartHttpServletRequest multipartRequest= (MultipartHttpServletRequest) request;</span><br><span class="line">            Map&lt;String, MultipartFile&gt; fileMap = multipartRequest.getFileMap();</span><br><span class="line">            <span class="comment">//遍历文件</span></span><br><span class="line">            Iterator&lt;String&gt; iterator = fileMap.keySet().iterator();</span><br><span class="line">            <span class="keyword">while</span>(iterator.hasNext())&#123;</span><br><span class="line">                <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> iterator.next();</span><br><span class="line">                <span class="type">MultipartFile</span> <span class="variable">file</span> <span class="operator">=</span> multipartRequest.getFile(key);</span><br><span class="line">                <span class="type">String</span> <span class="variable">originalFilename</span> <span class="operator">=</span> file.getOriginalFilename();</span><br><span class="line">                <span class="type">String</span> <span class="variable">hz</span> <span class="operator">=</span> originalFilename.substring(originalFilename.lastIndexOf(<span class="string">&quot;.&quot;</span>));</span><br><span class="line">                <span class="comment">//判断后缀是否合法</span></span><br><span class="line">                <span class="keyword">if</span>(!hz.toLowerCase().equals(<span class="string">&quot;.png&quot;</span>) &amp;&amp; !hz.toLowerCase().equals(<span class="string">&quot;.jpg&quot;</span>))&#123;</span><br><span class="line">                    request.getRequestDispatcher(<span class="string">&quot;/jsp/fileTypError.jsp&quot;</span>).forward(request,response);</span><br><span class="line">                    flag=<span class="literal">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> flag;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上传文件类型错误跳转的页面fileError.jsp</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;fileError&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;h1&gt;文件上传的类型有误！后缀必须是.png或者是.jpg&lt;/h1&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="12-2-文件下载"><a href="#12-2-文件下载" class="headerlink" title="12.2 文件下载"></a>12.2 文件下载</h2><p>   (1）前端页面</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;form action=<span class="string">&quot;/file/download&quot;</span> method=<span class="string">&quot;post&quot;</span> enctype=<span class="string">&quot;multipart/form-data&quot;</span>&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span>&gt;下载图片--4e27abf2c3724985a0877599773143c6.jpg&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br></pre></td></tr></table></figure>

<p>   (2)配置处理类方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;download&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> ResponseEntity&lt;<span class="type">byte</span>[]&gt; download(HttpServletRequest request) <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="comment">//指定文件的路径-- 要保证指定的路径下有该文件才可以</span></span><br><span class="line">        String path=request.getServletContext().getRealPath(<span class="string">&quot;/uploadFile&quot;</span>)+<span class="string">&quot;/4e27abf2c3724985a0877599773143c6.jpg&quot;</span>;</span><br><span class="line">        <span class="comment">//创建响应 的头信息的对象</span></span><br><span class="line">        HttpHeaders headers=<span class="keyword">new</span> <span class="title class_">HttpHeaders</span>();</span><br><span class="line">        <span class="comment">//标记以流的方式作出响应</span></span><br><span class="line">        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);</span><br><span class="line">        <span class="comment">//以附件的形式响应给用户</span></span><br><span class="line">        headers.setContentDispositionFormData(<span class="string">&quot;attachment&quot;</span>,URLEncoder.encode(<span class="string">&quot;4e27abf2c3724985a0877599773143c6.jpg&quot;</span>,<span class="string">&quot;utf-8&quot;</span>));</span><br><span class="line">        File file=<span class="keyword">new</span> <span class="title class_">File</span>(path);</span><br><span class="line">        ResponseEntity&lt;<span class="type">byte</span>[]&gt; resp=<span class="keyword">new</span> <span class="title class_">ResponseEntity</span>&lt;&gt;(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);</span><br><span class="line">        <span class="keyword">return</span> resp;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p><img src="/img%5Cimage-20210329131132423.png" class="lazyload" data-srcset="/img%5Cimage-20210329131132423.png" srcset="" alt="image-20210329131132423"></p>
<h1 id="13、RESTful风格"><a href="#13、RESTful风格" class="headerlink" title="13、RESTful风格"></a>13、RESTful风格</h1><h2 id="13-1-REST概念"><a href="#13-1-REST概念" class="headerlink" title="13.1 REST概念"></a>13.1 REST概念</h2><p><strong>REST</strong>(英文：Representational State Transfer，简称<strong>REST</strong>，意思：表述性状态转换，描述了一个架构样式的网络系统，比如web应用)。</p>
<p>它是一种软件架构风格、设计风格，而不是标准，只是提供了一组设计原则和约束条件，它主要用于<strong>客户端和服务端</strong>交互类的软件。基于这个风格设计的软件可以更简洁，更有层次，更易于实现缓存等机制。</p>
<p>它本身并没有什么使用性，其核心价值在于如何设计出符合REST风格的网络接口。</p>
<h2 id="13-2-RESTful概念"><a href="#13-2-RESTful概念" class="headerlink" title="13.2 RESTful概念"></a>13.2 RESTful概念</h2><p>REST指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是<strong>RESTful</strong>。</p>
<p>RESTful的特性：</p>
<p>**资源(Resources)**：互联网所有的事物都可以被抽象为资源 。它可以是一段文本、一张图片、一首歌曲、一种服务，总之就是一个具体的存在。可以用一个URI（统一资源定位符）指向它，每种资源对应一个特性的URI。要获取这个资源，访问它的URI就可以，因此URI即为每一个资源的独一无二的识别符。</p>
<p>**表现层(Representation)**：把资源具体呈现出来的形式，叫做它的表现层(Representation)。比如，文本可以用txt格式表现，也可以用HTML格式、XML格式、JSON格式表现，甚至可以采用二进制格式。</p>
<p>**状态转换(State Transfer)**：每发出一个请求，就代表了客户端和服务器的一次交互过程。HTTP协议，是一个无状态协议，即所有的状态都保存在服务器端。因此，如果客户端想要操作服务器，必须通过某种手段，让服务器端发生“状态转换”(State Transfer)。而这种转换是建立在表现层之上的，所以就是“表现层状态转换”。</p>
<p>具体来说就是HTTP协议里面，四个表示操作方式的动词：<strong>GET、POST、PUT、DELETE</strong>。他们分别对应四种基本操作：GET用来<strong>获取</strong>资源，POST用来<strong>新建</strong>资源，PUT用来<strong>更新</strong>资源，DELETE用来<strong>删除</strong>资源。</p>
<p>原来的操作资源的方式：</p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/getExpress.do?id=1">http://localhost:8080/getExpress.do?id=1</a>      </p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/saveExpress.do">http://localhost:8080/saveExpress.do</a>           </p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/updateExpress.do">http://localhost:8080/updateExpress.do</a>        </p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/deleteExpress.do?id=1">http://localhost:8080/deleteExpress.do?id=1</a>  </p>
<p>原来用的方式当然没有问题，但是如果有更简洁的方式就更好了，此时就是RESTful风格。</p>
<p>使用RESTful操作资源：</p>
<p>GET	  &#x2F;expresses	      	#查询所有的快递信息列表</p>
<p>GET	   &#x2F;express&#x2F;1006		#查询一个快递信息</p>
<p>POST	 &#x2F;express	          	#新建一个快递信息</p>
<p>PUT	    &#x2F;express&#x2F;1006		#更新一个快递信息(全部更新)</p>
<p>PATCH    &#x2F;express&#x2F;1006		#更新一个快递信息（部分更新）</p>
<p>DELETE	&#x2F;express&#x2F;1006		#删除一个快递信息</p>
<h2 id="13-3-API设计-URL设计"><a href="#13-3-API设计-URL设计" class="headerlink" title="13.3 API设计&#x2F;URL设计"></a>13.3 API设计&#x2F;URL设计</h2><h3 id="13-3-1-动词-宾语"><a href="#13-3-1-动词-宾语" class="headerlink" title="13.3.1 动词+宾语"></a>13.3.1 动词+宾语</h3><p>RESTful 的核心思想就是客户端的用户发出的数据操作指令都是”动词 + 宾语”的结构。例如GET &#x2F;expresses 这个命令，GET是动词，&#x2F;expresses 是宾语。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">动词通常就是五种 HTTP 方法，对应 CRUD 操作。</span><br><span class="line">    GET：读取（Read）</span><br><span class="line">    POST：新建（Create）</span><br><span class="line">    PUT：更新（Update）</span><br><span class="line">    PATCH：更新（Update），通常是部分更新</span><br><span class="line">    DELETE：删除（Delete）</span><br><span class="line"></span><br><span class="line">PS: 1、根据 HTTP 规范，动词一律大写。</span><br><span class="line">	2、一些代理只支持POST和GET方法， 为了使用这些有限方法支持RESTful API，需要一种办法覆盖http原来的方法。使用订制的HTTP头 X-HTTP-Method-Override 来覆盖POST 方法.</span><br></pre></td></tr></table></figure>

<h3 id="13-3-2-宾语必须是名词"><a href="#13-3-2-宾语必须是名词" class="headerlink" title="13.3.2 宾语必须是名词"></a>13.3.2 宾语必须是名词</h3><p>宾语就是 API 的 URL，是 HTTP 动词作用的对象。它应该是名词，不能是动词。</p>
<p>比如，&#x2F;expresses 这个 URL 就是正确的。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">以下这些URL都是不推荐的，因为带上了动词，不是推荐写法。</span><br><span class="line">/getAllExpresses</span><br><span class="line">/getExpress</span><br><span class="line">/createExpress</span><br><span class="line">/deleteAllExpress</span><br></pre></td></tr></table></figure>

<blockquote>
<p>ps:不要混淆名词单数和复数，为了保持简单，只对所有资源使用复数。</p>
</blockquote>
<h3 id="13-3-3-避免多级URL"><a href="#13-3-3-避免多级URL" class="headerlink" title="13.3.3 避免多级URL"></a>13.3.3 避免多级URL</h3><p>如果资源中有多级分类，也不建议写出多级的URL。例如要获取球队中某个队员，有人可能这么写：</p>
<p>GET	&#x2F;team&#x2F;1001&#x2F;player&#x2F;1005</p>
<p>这种写法的语义不够明确，所以推荐使用查询字符串做后缀，改写为</p>
<p>GET	&#x2F;team&#x2F;1001?player&#x3D;1005.</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">再例如查询所有的还未取出的快递，你该如何编写呢？</span><br><span class="line">GET	/expresses/statu  不推荐 </span><br><span class="line">GET	/expresses?statu=false  推荐</span><br></pre></td></tr></table></figure>

<h2 id="13-4-HTTP状态码"><a href="#13-4-HTTP状态码" class="headerlink" title="13.4 HTTP状态码"></a>13.4 HTTP状态码</h2><p>客户端的用户发起的每一次请求，服务器都必须给出响应。响应包括 <strong>HTTP 状态码</strong>和<strong>数据</strong>两部分。</p>
<p><strong>HTTP 状态码就是一个三位数，分成五个类别</strong>。这五大类总包含了100多种状态码（不需要全都记住，不用紧张哈，覆盖了绝大部分可能遇到的情况。每一种状态码都有标准的（或者约定的）解释，客户端只需查看状态码，就可以判断出发生了什么情况，所以服务器应该返回尽可能精确的状态码。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">五类状态码分别如下：</span><br><span class="line">    1xx：相关信息</span><br><span class="line">    2xx：操作成功</span><br><span class="line">    3xx：重定向</span><br><span class="line">    4xx：客户端错误</span><br><span class="line">    5xx：服务器错误</span><br><span class="line">    PS：API 不需要1xx状态码，所以这个类别直接忽略。</span><br></pre></td></tr></table></figure>

<h3 id="13-4-1-状态码2xx"><a href="#13-4-1-状态码2xx" class="headerlink" title="13.4.1 状态码2xx"></a>13.4.1 状态码2xx</h3><p><code>200</code>状态码表示操作成功，但是不同的方法可以返回更精确的状态码。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">GET: 200 OK  表示一切正常</span><br><span class="line">POST: 201 Created  表示新的资源已经成功创建</span><br><span class="line">PUT: 200 OK		</span><br><span class="line">PATCH: 200 OK</span><br><span class="line">DELETE: 204 No Content  表示资源已经成功删除</span><br></pre></td></tr></table></figure>

<h3 id="13-4-2-状态码3xx"><a href="#13-4-2-状态码3xx" class="headerlink" title="13.4.2 状态码3xx"></a>13.4.2 状态码3xx</h3><p>API 用不到<code>301</code>状态码（永久重定向）和<code>302</code>状态码（暂时重定向，<code>307</code>也是这个含义），因为它们可以由应用级别返回，浏览器会直接跳转，API 级别可以不考虑这两种情况。</p>
<p>API 用到的<code>3xx</code>状态码，主要是<code>303 See Other</code>，表示参考另一个 URL。它与<code>302</code>和<code>307</code>的含义一样，也是”暂时重定向”，区别在于<code>302</code>和<code>307</code>用于<code>GET</code>请求，而<code>303</code>用于<code>POST</code>、<code>PUT</code>和<code>DELETE</code>请求。收到<code>303</code>以后，浏览器不会自动跳转，而会让用户自己决定下一步怎么办。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">我们只需要关注一下304状态码就可以了</span><br><span class="line">304 ： Not Modified  客户端使用缓存数据</span><br></pre></td></tr></table></figure>

<h3 id="13-4-3-状态码4xx"><a href="#13-4-3-状态码4xx" class="headerlink" title="13.4.3 状态码4xx"></a>13.4.3 状态码4xx</h3><p><code>4xx</code>状态码表示客户端错误。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">400 Bad Request：服务器不理解客户端的请求，未做任何处理。</span><br><span class="line">401 Unauthorized：用户未提供身份验证凭据，或者没有通过身份验证。</span><br><span class="line">403 Forbidden：用户通过了身份验证，但是不具有访问资源所需的权限。</span><br><span class="line">404 Not Found：所请求的资源不存在，或不可用。</span><br><span class="line">405 Method Not Allowed：用户已经通过身份验证，但是所用的 HTTP 方法不在他的权限之内。</span><br><span class="line">410 Gone：所请求的资源已从这个地址转移，不再可用。</span><br><span class="line">415 Unsupported Media Type：客户端要求的返回格式不支持。比如，API 只能返回 JSON 格式，但是客户端要求返回 XML 格式。</span><br><span class="line">422 Unprocessable Entity ：客户端上传的附件无法处理，导致请求失败。</span><br><span class="line">429 Too Many Requests：客户端的请求次数超过限额。</span><br></pre></td></tr></table></figure>

<h3 id="13-4-4-状态码5xx"><a href="#13-4-4-状态码5xx" class="headerlink" title="13.4.4 状态码5xx"></a>13.4.4 状态码5xx</h3><p><code>5xx</code>状态码表示服务端错误。一般来说，API 不会向用户透露服务器的详细信息，所以只要两个状态码就够了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">500 Internal Server Error：客户端请求有效，服务器处理时发生了意外。</span><br><span class="line">503 Service Unavailable：服务器无法处理请求，一般用于网站维护状态。</span><br></pre></td></tr></table></figure>

<h2 id="13-5-服务器响应"><a href="#13-5-服务器响应" class="headerlink" title="13.5 服务器响应"></a>13.5 服务器响应</h2><p>服务器返回的信息一般不推荐纯文本，而是建议大家选择JSON 对象，因为这样才能返回标准的结构化数据。</p>
<p>所以，服务器回应的 HTTP 头的<code>Content-Type</code>属性要设为<code>application/json</code>。客户端请求时，也要明确告诉服务器，可以接受 JSON 格式，即请求的 HTTP 头的<code>ACCEPT</code>属性也要设成<code>application/json</code>。</p>
<p>当发生错误的时候，除了返回状态码之外，也要返回错误信息。所以我们可以自己封装要返回的信息。</p>
<h2 id="13-6-案例"><a href="#13-6-案例" class="headerlink" title="13.6 案例"></a>13.6 案例</h2><h3 id="13-6-1RESTful风格的查询"><a href="#13-6-1RESTful风格的查询" class="headerlink" title="13.6.1RESTful风格的查询"></a>13.6.1RESTful风格的查询</h3><p>前端页面restful.jsp</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;restful&lt;/title&gt;</span><br><span class="line">    &lt;script src=<span class="string">&quot;/js/jquery-1.11.1.js&quot;</span>&gt;&lt;/script&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;form id=<span class="string">&quot;myForm&quot;</span> action=<span class="string">&quot;&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">        球队ID:&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamId&quot;</span> id=<span class="string">&quot;teamId&quot;</span> /&gt;&lt;br/&gt;</span><br><span class="line">        球队名称:&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;teamName&quot;</span> /&gt;&lt;br/&gt;</span><br><span class="line">        球队位置:&lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;location&quot;</span> /&gt;&lt;br/&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;button&quot;</span> id=<span class="string">&quot;btnGetAll&quot;</span>&gt;查询所有GET&lt;/button&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;button&quot;</span> id=<span class="string">&quot;btnGetOne&quot;</span>&gt;查询单个GET&lt;/button&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;button&quot;</span> id=<span class="string">&quot;btnPost&quot;</span>&gt;添加POST&lt;/button&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;button&quot;</span> id=<span class="string">&quot;btnPut&quot;</span>&gt;更新PUT&lt;/button&gt;</span><br><span class="line">        &lt;button type=<span class="string">&quot;button&quot;</span> id=<span class="string">&quot;btnDel&quot;</span>&gt;删除DELETE&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">    &lt;p id=<span class="string">&quot;showResult&quot;</span>&gt;&lt;/p&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">    <span class="comment">//页面加载完毕之后给按钮绑定事件</span></span><br><span class="line">    $(function () &#123;</span><br><span class="line">        <span class="comment">//给 查询所有GET 按钮绑定单击事件</span></span><br><span class="line">        $(<span class="string">&quot;#btnGetAll&quot;</span>).click(function () &#123;</span><br><span class="line">            <span class="comment">//发起异步请求</span></span><br><span class="line">            $.ajax(&#123;</span><br><span class="line">                type: <span class="string">&quot;GET&quot;</span>,</span><br><span class="line">                url: <span class="string">&quot;/teams&quot;</span>, <span class="comment">//RESTful风格的API定义</span></span><br><span class="line">                data: <span class="string">&quot;&quot;</span>,</span><br><span class="line">                dataType:<span class="string">&quot;json&quot;</span>,</span><br><span class="line">                success: function(list)&#123;</span><br><span class="line">                    alert( <span class="string">&quot;Data Saved: &quot;</span> + list );</span><br><span class="line">                    <span class="keyword">var</span> str=<span class="string">&quot;&quot;</span>;</span><br><span class="line">                    <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i&lt;list.length;i++)&#123;</span><br><span class="line">                        <span class="keyword">var</span> obj=list[i];</span><br><span class="line">                        str+=obj.teamId+<span class="string">&quot;----&quot;</span>+obj.teamName+<span class="string">&quot;----&quot;</span>+obj.location+<span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                    $(<span class="string">&quot;#showResult&quot;</span>).html(str);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//给 查询单个GET 按钮绑定单击事件</span></span><br><span class="line">        $(<span class="string">&quot;#btnGetOne&quot;</span>).click(function () &#123;</span><br><span class="line">            <span class="comment">//发起异步请求</span></span><br><span class="line">            $.ajax(&#123;</span><br><span class="line">                type: <span class="string">&quot;GET&quot;</span>,</span><br><span class="line">                url: <span class="string">&quot;/team/&quot;</span>+$(<span class="string">&quot;#teamId&quot;</span>).val(), <span class="comment">//RESTful风格的API定义</span></span><br><span class="line">                data: <span class="string">&quot;&quot;</span>,</span><br><span class="line">                dataType:<span class="string">&quot;json&quot;</span>,</span><br><span class="line">                success: function(obj)&#123;</span><br><span class="line">                    alert( <span class="string">&quot;Data Saved: &quot;</span> + obj );</span><br><span class="line">                    <span class="keyword">if</span>(obj==<span class="string">&quot;&quot;</span>)&#123;</span><br><span class="line">                        $(<span class="string">&quot;#showResult&quot;</span>).html(<span class="string">&quot;没有复合条件的数据！&quot;</span>);</span><br><span class="line">                    &#125;<span class="keyword">else</span></span><br><span class="line">                     $(<span class="string">&quot;#showResult&quot;</span>).html(obj.teamId+<span class="string">&quot;----&quot;</span>+obj.teamName+<span class="string">&quot;----&quot;</span>+obj.location+<span class="string">&quot;&lt;br/&gt;&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>控制器RestfulController.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.lina.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.lina.pojo.Team;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.PathVariable;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMethod;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.ResponseBody;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ClassName: RestfulController</span></span><br><span class="line"><span class="comment"> * restful风格的控制器</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> wanglina</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RestfulController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> List&lt;Team&gt; teamList;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        teamList=<span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;(<span class="number">3</span>);</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=<span class="number">3</span>;i++)&#123;</span><br><span class="line">            Team team=<span class="keyword">new</span> <span class="title class_">Team</span>();</span><br><span class="line">            team.setTeamId(<span class="number">1000</span>+i);</span><br><span class="line">            team.setTeamName(<span class="string">&quot;湖人&quot;</span>+i);</span><br><span class="line">            team.setLocation(<span class="string">&quot;洛杉矶&quot;</span>+i);</span><br><span class="line">            teamList.add(team);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询所有的球队</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(value = &quot;/teams&quot;,method = RequestMethod.GET)</span></span><br><span class="line">    <span class="meta">@ResponseBody</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Team&gt; <span class="title function_">getAll</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;查询所有GET--发起的请求---------&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> teamList;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据id 查询单个的球队：</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(value = &quot;/team/&#123;id&#125;&quot;,method = RequestMethod.GET)</span></span><br><span class="line">    <span class="meta">@ResponseBody</span></span><br><span class="line">    <span class="keyword">public</span> Team <span class="title function_">getOne</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span><span class="type">int</span> id)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;查询单个GET--发起的请求---------&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (Team team : teamList) &#123;</span><br><span class="line">            <span class="keyword">if</span>(team.getTeamId()==id)&#123;<span class="comment">//整数比对值：所以方法参数写为int而不是Integer</span></span><br><span class="line">                <span class="keyword">return</span> team;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;hello&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">hello</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;restful&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="13-6-2RESTful风格的添加"><a href="#13-6-2RESTful风格的添加" class="headerlink" title="13.6.2RESTful风格的添加"></a>13.6.2RESTful风格的添加</h3><p>前端页面上脚本中添加如下内容：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//给 添加POST 按钮绑定单击事件</span></span><br><span class="line">      $(<span class="string">&quot;#btnPost&quot;</span>).<span class="title function_">click</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="title function_">alert</span>($(<span class="string">&quot;#myForm&quot;</span>).<span class="title function_">serialize</span>());</span><br><span class="line">          <span class="comment">//发起异步请求</span></span><br><span class="line">          $.<span class="title function_">ajax</span>(&#123;</span><br><span class="line">              <span class="attr">type</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">              <span class="attr">url</span>: <span class="string">&quot;/team&quot;</span>, <span class="comment">//RESTful风格的API定义</span></span><br><span class="line">              <span class="attr">data</span>: $(<span class="string">&quot;#myForm&quot;</span>).<span class="title function_">serialize</span>(),<span class="comment">//表单的所有数据以？&amp;形式追加在URL后面 /team?teamId=1006&amp;teamName=kuaichuan&amp;location=las</span></span><br><span class="line">              <span class="attr">dataType</span>:<span class="string">&quot;json&quot;</span>,</span><br><span class="line">              <span class="attr">success</span>: <span class="keyword">function</span>(<span class="params">msg</span>)&#123;</span><br><span class="line">                  <span class="comment">//alert( &quot;Data Saved: &quot; + msg );</span></span><br><span class="line">                  $(<span class="string">&quot;#showResult&quot;</span>).<span class="title function_">html</span>(msg);</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;);</span><br><span class="line">      &#125;);</span><br></pre></td></tr></table></figure>

<p>控制器中添加方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">    * 添加一个球队</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">   <span class="meta">@RequestMapping(value = &quot;team&quot;,method = RequestMethod.POST)</span></span><br><span class="line">   <span class="meta">@ResponseBody</span></span><br><span class="line">   <span class="keyword">public</span> String <span class="title function_">add</span><span class="params">(Team team)</span>&#123;</span><br><span class="line">       System.out.println(<span class="string">&quot;添加POST--发起的请求---------&quot;</span>);</span><br><span class="line">       teamList.add(team);</span><br><span class="line">       <span class="keyword">return</span> <span class="string">&quot;201&quot;</span>;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<h3 id="13-6-3-RESTful风格的更新"><a href="#13-6-3-RESTful风格的更新" class="headerlink" title="13.6.3 RESTful风格的更新"></a>13.6.3 RESTful风格的更新</h3><p>前端页面上脚本中添加如下内容：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">$(<span class="string">&quot;#btnPut&quot;</span>).<span class="title function_">click</span>(<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">            <span class="title function_">alert</span>($(<span class="string">&quot;#myForm&quot;</span>).<span class="title function_">serialize</span>());</span><br><span class="line">            $.<span class="title function_">ajax</span>(&#123;</span><br><span class="line">                <span class="attr">type</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">                <span class="attr">url</span>: <span class="string">&quot;/team/&quot;</span>+$(<span class="string">&quot;#teamId&quot;</span>).<span class="title function_">val</span>(),</span><br><span class="line">                <span class="attr">data</span>: $(<span class="string">&quot;#myForm&quot;</span>).<span class="title function_">serialize</span>()+<span class="string">&quot;&amp;_method=PUT&quot;</span>,</span><br><span class="line">                <span class="attr">dataType</span>:<span class="string">&quot;json&quot;</span>,</span><br><span class="line">                <span class="comment">//headers:&#123;&quot;X-HTTP-Method-Override&quot;:&quot;GET&quot;&#125;,</span></span><br><span class="line">                <span class="attr">success</span>: <span class="keyword">function</span>(<span class="params">msg</span>)&#123;</span><br><span class="line">                    $(<span class="string">&quot;#showResult&quot;</span>).<span class="title function_">html</span>(msg);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br></pre></td></tr></table></figure>

<p>控制器中添加方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(value = &quot;/team/&#123;id&#125;&quot;,method = RequestMethod.PUT)</span></span><br><span class="line">    <span class="meta">@ResponseBody</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">update</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span> <span class="type">int</span> id,Team newTeam)</span>&#123;</span><br><span class="line">        System.out.println(id);</span><br><span class="line">        <span class="keyword">for</span> (Team team : teamList) &#123;</span><br><span class="line">            <span class="keyword">if</span>(team.getTeamId()==id)&#123;</span><br><span class="line">                team.setTeamName(newTeam.getTeamName());</span><br><span class="line">                team.setLocation(newTeam.getLocation());</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;204&quot;</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;404&quot;</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h3 id="13-6-4RESTful风格的删除"><a href="#13-6-4RESTful风格的删除" class="headerlink" title="13.6.4RESTful风格的删除"></a>13.6.4RESTful风格的删除</h3><p>前端页面上脚本中添加如下内容：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//给 删除DELETE 按钮绑定单击事件</span></span><br><span class="line">        $(<span class="string">&quot;#btnDel&quot;</span>).<span class="title function_">click</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">            <span class="title function_">alert</span>($(<span class="string">&quot;#myForm&quot;</span>).<span class="title function_">serialize</span>());</span><br><span class="line">            <span class="comment">//发起异步请求</span></span><br><span class="line">            $.<span class="title function_">ajax</span>(&#123;</span><br><span class="line">                <span class="attr">type</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">                <span class="attr">url</span>: <span class="string">&quot;/team/&quot;</span>+$(<span class="string">&quot;#teamId&quot;</span>).<span class="title function_">val</span>(), <span class="comment">//RESTful风格的API定义</span></span><br><span class="line">                <span class="attr">data</span>: <span class="string">&quot;_method=DELETE&quot;</span>,</span><br><span class="line">                <span class="attr">success</span>: <span class="keyword">function</span>(<span class="params">msg</span>)&#123;</span><br><span class="line">                    <span class="comment">//alert( &quot;Data Saved: &quot; + msg );</span></span><br><span class="line">                    $(<span class="string">&quot;#showResult&quot;</span>).<span class="title function_">html</span>(msg);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br></pre></td></tr></table></figure>

<p>控制器中添加方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据ID删除一个球队</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(value = &quot;team/&#123;id&#125;&quot;,method = RequestMethod.DELETE)</span></span><br><span class="line">    <span class="meta">@ResponseBody</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">del</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span><span class="type">int</span> id)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;删除DELETE--发起的请求---------&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (Team team1 : teamList) &#123;</span><br><span class="line">            <span class="keyword">if</span>(team1.getTeamId()==id)&#123;</span><br><span class="line">                teamList.remove(team1);</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;204&quot;</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;500&quot;</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h3 id="13-6-5-RESTful风格的更新和删除遇到的问题"><a href="#13-6-5-RESTful风格的更新和删除遇到的问题" class="headerlink" title="13.6.5 RESTful风格的更新和删除遇到的问题"></a>13.6.5 RESTful风格的更新和删除遇到的问题</h3><h4 id="13-6-5-1-遇到的问题："><a href="#13-6-5-1-遇到的问题：" class="headerlink" title="13.6.5.1 遇到的问题："></a>13.6.5.1 遇到的问题：</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">在Ajax中，采用Restful风格PUT和DELETE请求传递参数无效，传递到后台的参数值为null</span><br></pre></td></tr></table></figure>

<h4 id="13-6-5-2-产生的原因："><a href="#13-6-5-2-产生的原因：" class="headerlink" title="13.6.5.2 产生的原因："></a>13.6.5.2 产生的原因：</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Tomcat封装请求参数的过程：</span><br><span class="line">    1.将请求体中的数据，封装成一个map</span><br><span class="line">    2.request.getParameter(key)会从这个map中取值</span><br><span class="line">    3.SpringMvc封装POJO对象的时候，会把POJO中每个属性的值进行request.getParamter();</span><br><span class="line"> AJAX发送PU或者DELETE请求时，请求体中的数据通过request.getParamter()拿不到。</span><br><span class="line"> Tomcat一检测到是PUT或者DELETE就不会封装请求体中的数据为map，只有POST形式的请求才封装请求为map。</span><br></pre></td></tr></table></figure>

<h3 id="13-6-5-3-解决方案："><a href="#13-6-5-3-解决方案：" class="headerlink" title="13.6.5.3 解决方案："></a>13.6.5.3 解决方案：</h3><p>1、前端页面中的ajax发送请求的时候在url中加<code>&amp;_method=”PUT”</code>或者<code>&amp;_method=”DELETE”</code>即可</p>
<p><img src="/img%5Cimage-20210329195045446.png" class="lazyload" data-srcset="/img%5Cimage-20210329195045446.png" srcset="" alt="image-20210329195045446"></p>
<p>2、web.xml中配置</p>
<p>配置的时候多个过滤器需要注意顺序</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 使用Rest风格的URI 将页面普通的post请求转为指定的delete或者put请求</span></span><br><span class="line"><span class="comment">原理：在Aajx中发送post请求后，带_method参数，将其修改为PUT，或者DELETE请求--&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">filter</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>httpMethodFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-class</span>&gt;</span></span><br><span class="line">            org.springframework.web.filter.HiddenHttpMethodFilter</span><br><span class="line">        <span class="tag">&lt;/<span class="name">filter-class</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">filter</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>httpMethodFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/*<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">filter-mapping</span>&gt;</span></span><br></pre></td></tr></table></figure>

  </div>
  
  
    
    <div class='footer'>
       <!-- 参考资料、相关资料等 -->
      
       <!-- 相关文章 -->
      
      <!-- 版权声明组件 -->
      
      <!-- 打赏组件 -->
      
    </div>
  
  
    


  <div class='article-meta' id="bottom">
    <div class='new-meta-box'>
      
        
          <div class="new-meta-item date" itemprop="dateModified" datetime="2024-01-15T19:27:56+08:00">
  <a class='notlink'>
    <i class="fa-solid fa-edit fa-fw" aria-hidden="true"></i>
    <p>更新于：Jan 15, 2024</p>
  </a>
</div>

        
      
        
          

        
      
        
          
  <div class="new-meta-item share -mob-share-list">
  <div class="-mob-share-list share-body">
    
      
        <a class="-mob-share-qq" title="" rel="external nofollow noopener noreferrer noopener"
          
          target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://8.219.11.28/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-SpringMVC%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/&title= - 欢迎来到我的个人博客~&summary="
          
          >
          
            <img src="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/qq.png" class="lazyload" data-srcset="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/qq.png" srcset="">
          
        </a>
      
    
      
        <a class="-mob-share-qzone" title="" rel="external nofollow noopener noreferrer noopener"
          
          target="_blank" href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=http://8.219.11.28/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-SpringMVC%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/&title= - 欢迎来到我的个人博客~&summary="
          
          >
          
            <img src="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/qzone.png" class="lazyload" data-srcset="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/qzone.png" srcset="">
          
        </a>
      
    
      
        <a class="-mob-share-weibo" title="" rel="external nofollow noopener noreferrer noopener"
          
          target="_blank" href="http://service.weibo.com/share/share.php?url=http://8.219.11.28/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-SpringMVC%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/&title= - 欢迎来到我的个人博客~&summary="
          
          >
          
            <img src="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/weibo.png" class="lazyload" data-srcset="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/weibo.png" srcset="">
          
        </a>
      
    
      
    
      
    
  </div>
</div>



        
      
    </div>
    <!-- Custom Files bottomMeta begin -->
    
    <!-- Custom Files bottomMeta end -->
  </div>


  
  

  
    <div class="prev-next">
      
        <a class='prev' href='/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-SpringSecurity/'>
          <p class='title'><i class="fa-solid fa-chevron-left" aria-hidden="true"></i>Feb 23, 2024</p>
          <p class='content'>SpringSecurity概念Spring家族当中，一个安全管理框架。
Shiro也是一个安全框架，提供了很多安全功能。Shiro比较老，旧的项目当中，可能还在使用。上手还挺简单。
在新项目当...</p>
        </a>
      
      
        <a class='next' href='/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-Spring%E6%A1%86%E6%9E%B6%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/'>
          <p class='title'>Feb 23, 2024<i class="fa-solid fa-chevron-right" aria-hidden="true"></i></p>
          <p class='content'>Spring框架课堂笔记Spring概述，ioC ， DI ，AOP ，整合JDBC ，事务管理
1. Spring概述1.1 什么是框架？框架（Framework）：框（指其约束性）架（指其支...</p>
        </a>
      
    </div>
  
  <!-- Custom Files postEnd begin-->
  
  <!-- Custom Files postEnd end-->
</article>


  


  <article class="post white-box shadow floatable blur" id="comments">
    <span hidden>
      <meta itemprop="discussionUrl" content="/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-SpringMVC%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/index.html#comments">
    </span>
    <p ct><i class='fa-solid fa-comments'></i> 评论</p>
    

    <div id="layoutHelper-comments"></div>

  </article>






</div>
<aside id='l_side' itemscope itemtype="http://schema.org/WPSideBar">
  

  
    
    
      
    
  


<div class="widget-sticky pjax">

  
  


  <section class="widget toc-wrapper desktop mobile " id="toc-div" >
    
  <header>
    
      <i class="fa-solid fa-list fa-fw" aria-hidden="true"></i><span class='name'>本文目录</span>
    
  </header>


    <div class='content'>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-1-SpringMVC%E6%A6%82%E5%BF%B5"><span class="toc-text">1.1 SpringMVC概念</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#1-2-SpringMVC%E5%8E%9F%E7%90%86"><span class="toc-text">1.2 SpringMVC原理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#1-3-SpringMVC%E4%BC%98%E5%8A%BF"><span class="toc-text">1.3 SpringMVC优势</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-1-%E5%88%9B%E5%BB%BAmaven%E9%A1%B9%E7%9B%AE"><span class="toc-text">3.1 创建maven项目</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-2-pom-xml%E6%96%87%E4%BB%B6%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96%E5%92%8C%E6%8F%92%E4%BB%B6"><span class="toc-text">3.2 pom.xml文件添加依赖和插件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-3-%E5%88%9B%E5%BB%BASpring%E5%92%8CSpringMVC%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="toc-text">3.3 创建Spring和SpringMVC的配置文件</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3-1-%E5%88%9B%E5%BB%BASpring%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6applicationContext-xml%E6%96%87%E4%BB%B6"><span class="toc-text">3.3.1 创建Spring配置文件applicationContext.xml文件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3-2-%E5%88%9B%E5%BB%BASpringMVC%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6springmvc-xml"><span class="toc-text">3.3.2 创建SpringMVC的配置文件springmvc.xml</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-4-%E5%9C%A8web-xml%E4%B8%AD%E8%BF%9B%E8%A1%8CSpring%E5%92%8CSpringMVC%E9%85%8D%E7%BD%AE"><span class="toc-text">3.4 在web.xml中进行Spring和SpringMVC配置</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-5-%E5%88%9B%E5%BB%BA%E6%8E%A7%E5%88%B6%E5%99%A8"><span class="toc-text">3.5 创建控制器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-6-%E9%85%8D%E7%BD%AE%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90%E5%99%A8"><span class="toc-text">3.6 配置视图解析器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-7-%E7%BC%96%E5%86%99index-jsp%E9%A1%B5%E9%9D%A2"><span class="toc-text">3.7 编写index.jsp页面</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-8-%E6%B5%8B%E8%AF%95"><span class="toc-text">3.8 测试</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-9-%E8%A7%A3%E6%9E%90"><span class="toc-text">3.9 解析</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-1-%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90"><span class="toc-text">4.1 工作流程分析</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-2-SpringMVC%E7%BB%84%E4%BB%B6"><span class="toc-text">4.2 SpringMVC组件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-1-RequestMapping%E5%87%BA%E7%8E%B0%E7%9A%84%E4%BD%8D%E7%BD%AE"><span class="toc-text">5.1@RequestMapping出现的位置</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-2-%E6%8C%87%E5%AE%9A%E8%AF%B7%E6%B1%82%E6%8F%90%E4%BA%A4%E6%96%B9%E5%BC%8F"><span class="toc-text">5.2 指定请求提交方式</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-3-%E8%A1%A5%E5%85%85url-pattern%E8%A7%A3%E6%9E%90"><span class="toc-text">5.3 补充url-pattern解析</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#5-3-1-url-pattern%E8%A7%A3%E6%9E%90"><span class="toc-text">5.3.1 url-pattern解析</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-3-2-%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E8%AE%BF%E9%97%AE"><span class="toc-text">5.3.2 静态资源访问</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#5-3-2-1%E4%BD%BF%E7%94%A8-mvc-default-servlet-handler"><span class="toc-text">5.3.2.1使用&lt; mvc:default-servlet-handler&#x2F; &gt;</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-3-2-2-%E4%BD%BF%E7%94%A8-mvc-resources"><span class="toc-text">5.3.2.2 使用 &lt; mvc:resources&#x2F; &gt;</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-1-%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%E7%9A%84%E5%8F%82%E6%95%B0%E9%80%90%E4%B8%AA%E6%8E%A5%E6%94%B6"><span class="toc-text">6.1 直接使用方法的参数逐个接收</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-2-%E4%BD%BF%E7%94%A8%E5%AF%B9%E8%B1%A1%E6%8E%A5%E6%94%B6%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0"><span class="toc-text">6.2 使用对象接收多个参数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-3-%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E5%92%8C%E6%96%B9%E6%B3%95%E5%90%8D%E7%A7%B0%E7%9A%84%E5%8F%82%E6%95%B0%E4%B8%8D%E4%B8%80%E8%87%B4"><span class="toc-text">6.3 请求参数和方法名称的参数不一致</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-4-%E4%BD%BF%E7%94%A8HttpServletRequest-%E5%AF%B9%E8%B1%A1%E8%8E%B7%E5%8F%96%E5%8F%82%E6%95%B0"><span class="toc-text">6.4 使用HttpServletRequest 对象获取参数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-5-%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8URL%E5%9C%B0%E5%9D%80%E4%BC%A0%E5%8F%82"><span class="toc-text">6.5 直接使用URL地址传参</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-6-%E8%8E%B7%E5%8F%96%E6%97%A5%E6%9C%9F%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%82%E6%95%B0"><span class="toc-text">6.6 获取日期类型的参数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-7-%E8%8E%B7%E5%8F%96%E6%95%B0%E7%BB%84%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%82%E6%95%B0"><span class="toc-text">6.7 获取数组类型的参数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-8-%E8%8E%B7%E5%8F%96%E9%9B%86%E5%90%88%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%82%E6%95%B0"><span class="toc-text">6.8 获取集合类型的参数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7-1-%E4%B9%B1%E7%A0%81%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88"><span class="toc-text">7.1 乱码解决方案</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7-2-%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%E5%8E%9F%E7%90%86"><span class="toc-text">7.2 解决方案原理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8-1-%E8%BF%94%E5%9B%9EModelAndView"><span class="toc-text">8.1 返回ModelAndView</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8-2-%E8%BF%94%E5%9B%9EString"><span class="toc-text">8.2 返回String</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8-3-%E8%BF%94%E5%9B%9E%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B"><span class="toc-text">8.3 返回对象类型</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#8-3-1-%E8%BF%94%E5%9B%9E%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B"><span class="toc-text">8.3.1 返回基础类型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#8-3-2-%E8%BF%94%E5%9B%9E%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E7%B1%BB%E5%9E%8B"><span class="toc-text">8.3.2 返回自定义对象类型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#8-3-3-%E8%BF%94%E5%9B%9E%E9%9B%86%E5%90%88List"><span class="toc-text">8.3.3 返回集合List</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#8-3-4-%E8%BF%94%E5%9B%9E%E9%9B%86%E5%90%88Map"><span class="toc-text">8.3.4 返回集合Map</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8-4-%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC-void-%E4%BA%86%E8%A7%A3"><span class="toc-text">8.4 无返回值 void-了解</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9-1-%E8%BD%AC%E5%8F%91%E5%88%B0%E4%B8%80%E4%B8%AAjsp%E9%A1%B5%E9%9D%A2"><span class="toc-text">9.1 转发到一个jsp页面</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#9-1-1-%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%96%B9%E5%BC%8F%E8%BD%AC%E5%8F%91"><span class="toc-text">9.1.1 字符串方式转发</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-1-2-ModelAndView%E8%BD%AC%E5%8F%91"><span class="toc-text">9.1.2 ModelAndView转发</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9-2-%E9%87%8D%E5%AE%9A%E5%90%91%E5%88%B0%E4%B8%80%E4%B8%AAjsp%E9%A1%B5%E9%9D%A2"><span class="toc-text">9.2 重定向到一个jsp页面</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#9-2-1-%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%96%B9%E5%BC%8F%E9%87%8D%E5%AE%9A%E5%90%91"><span class="toc-text">9.2.1 字符串方式重定向</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-2-2-ModelAndView%E9%87%8D%E5%AE%9A%E5%90%91%E6%96%B9%E5%BC%8F"><span class="toc-text">9.2.2 ModelAndView重定向方式</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9-3-%E9%87%8D%E5%AE%9A%E5%90%91%E6%88%96%E8%80%85%E8%BD%AC%E5%8F%91%E5%88%B0%E6%8E%A7%E5%88%B6%E5%99%A8"><span class="toc-text">9.3 重定向或者转发到控制器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10-1-ExceptionHandler-%E6%B3%A8%E8%A7%A3"><span class="toc-text">10.1@ExceptionHandler 注解</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10-2-%E5%AE%9E%E7%8E%B0%E6%AD%A5%E9%AA%A4"><span class="toc-text">10.2 实现步骤</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#10-2-1-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BC%82%E5%B8%B8%E7%B1%BB"><span class="toc-text">10.2.1 自定义异常类</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10-3%E4%BC%98%E5%8C%96"><span class="toc-text">10.3优化</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#11-1-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8B%A6%E6%88%AA%E5%99%A8"><span class="toc-text">11.1 自定义拦截器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#11-2-%E9%85%8D%E7%BD%AE%E6%8B%A6%E6%88%AA%E5%99%A8"><span class="toc-text">11.2 配置拦截器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#12-1-%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0"><span class="toc-text">12.1 文件上传</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#12-2-%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD"><span class="toc-text">12.2 文件下载</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13-1-REST%E6%A6%82%E5%BF%B5"><span class="toc-text">13.1 REST概念</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13-2-RESTful%E6%A6%82%E5%BF%B5"><span class="toc-text">13.2 RESTful概念</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13-3-API%E8%AE%BE%E8%AE%A1-URL%E8%AE%BE%E8%AE%A1"><span class="toc-text">13.3 API设计&#x2F;URL设计</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#13-3-1-%E5%8A%A8%E8%AF%8D-%E5%AE%BE%E8%AF%AD"><span class="toc-text">13.3.1 动词+宾语</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-3-2-%E5%AE%BE%E8%AF%AD%E5%BF%85%E9%A1%BB%E6%98%AF%E5%90%8D%E8%AF%8D"><span class="toc-text">13.3.2 宾语必须是名词</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-3-3-%E9%81%BF%E5%85%8D%E5%A4%9A%E7%BA%A7URL"><span class="toc-text">13.3.3 避免多级URL</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13-4-HTTP%E7%8A%B6%E6%80%81%E7%A0%81"><span class="toc-text">13.4 HTTP状态码</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#13-4-1-%E7%8A%B6%E6%80%81%E7%A0%812xx"><span class="toc-text">13.4.1 状态码2xx</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-4-2-%E7%8A%B6%E6%80%81%E7%A0%813xx"><span class="toc-text">13.4.2 状态码3xx</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-4-3-%E7%8A%B6%E6%80%81%E7%A0%814xx"><span class="toc-text">13.4.3 状态码4xx</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-4-4-%E7%8A%B6%E6%80%81%E7%A0%815xx"><span class="toc-text">13.4.4 状态码5xx</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13-5-%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%93%8D%E5%BA%94"><span class="toc-text">13.5 服务器响应</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13-6-%E6%A1%88%E4%BE%8B"><span class="toc-text">13.6 案例</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#13-6-1RESTful%E9%A3%8E%E6%A0%BC%E7%9A%84%E6%9F%A5%E8%AF%A2"><span class="toc-text">13.6.1RESTful风格的查询</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-6-2RESTful%E9%A3%8E%E6%A0%BC%E7%9A%84%E6%B7%BB%E5%8A%A0"><span class="toc-text">13.6.2RESTful风格的添加</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-6-3-RESTful%E9%A3%8E%E6%A0%BC%E7%9A%84%E6%9B%B4%E6%96%B0"><span class="toc-text">13.6.3 RESTful风格的更新</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-6-4RESTful%E9%A3%8E%E6%A0%BC%E7%9A%84%E5%88%A0%E9%99%A4"><span class="toc-text">13.6.4RESTful风格的删除</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-6-5-RESTful%E9%A3%8E%E6%A0%BC%E7%9A%84%E6%9B%B4%E6%96%B0%E5%92%8C%E5%88%A0%E9%99%A4%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-text">13.6.5 RESTful风格的更新和删除遇到的问题</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#13-6-5-1-%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%9A"><span class="toc-text">13.6.5.1 遇到的问题：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#13-6-5-2-%E4%BA%A7%E7%94%9F%E7%9A%84%E5%8E%9F%E5%9B%A0%EF%BC%9A"><span class="toc-text">13.6.5.2 产生的原因：</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-6-5-3-%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%EF%BC%9A"><span class="toc-text">13.6.5.3 解决方案：</span></a></li></ol></li></ol>
    </div>
  </section>

  

</div>


<!-- 没有 pjax 占位会报错 万恶的 pjax -->

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <!-- Custom Files side begin -->
  
  <!-- Custom Files side end -->
</aside>



          <!--此文件用来存放一些不方便取值的变量-->
<!--思路大概是将值藏到重加载的区域内-->

<pjax>
<script>
  window.pdata={}
  pdata.ispage=false;
  pdata.commentPath="";
  pdata.commentPlaceholder="";
  pdata.commentConfig={};
  //  see: /layout/_partial/scripts/_ctrl/coverCtrl.ejs
  
    // header
    var l_header=document.getElementById("l_header");
    
    l_header.classList.add("show");
    
    
      // cover
      var cover_wrapper=document.querySelector('#l_cover .cover-wrapper');
      var scroll_down=document.getElementById('scroll-down');
      cover_wrapper.id="none";
      cover_wrapper.style.display="none";
      scroll_down.style.display="none";
    
  
</script>
</pjax>
        </div>
        
  
  <footer class="footer clearfix"  itemscope itemtype="http://schema.org/WPFooter">
    <br><br>
    
      
        <div class="aplayer-container">
          


        </div>
      
    
      
        <br>
        <div class="social-wrapper" itemprop="about" itemscope itemtype="http://schema.org/Thing">
          
            
          
            
          
            
          
        </div>
      
    
      
        <div><p>Blog content follows the <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en">Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) License</a></p>
</div>
      
    
      
        
          <div><p><span id="lc-sv">本站总访问量为 <span id='number'><i class="fa-solid fa-loader fa-spin fa-fw" aria-hidden="true"></i></span> 次</span> <span id="lc-uv">访客数为 <span id='number'><i class="fa-solid fa-loader fa-spin fa-fw" aria-hidden="true"></i></span> 人</span></p>
</div>
        
      
    
      
        Use
        <a href="https://github.com/volantis-x/hexo-theme-volantis/#5.8.0" target="_blank" class="codename">Volantis</a>
        as theme
      
    
      
        <div class='copyright'>
        <p><a href="/">Copyright © since 2017 XXX</a></p>

        </div>
      
    
    <!-- Custom Files footer begin-->
    
    <!-- Custom Files footer end-->
  </footer>


        <a id="s-top" class="fa-solid fa-arrow-up fa-fw" href="/" onclick="return false;" title="top"></a>
      </div>
    </div>
    <div>
      <script>
  /******************** volantis.dom ********************************/
  // 页面选择器 将dom对象缓存起来 see: /source/js/app.js etc.
  volantis.dom.bodyAnchor = volantis.dom.$(document.getElementById("safearea")); // 页面主体
  volantis.dom.topBtn = volantis.dom.$(document.getElementById('s-top')); // 向上
  volantis.dom.wrapper = volantis.dom.$(document.getElementById('wrapper')); // 整个导航栏
  volantis.dom.coverAnchor = volantis.dom.$(document.querySelector('#l_cover .cover-wrapper')); // 1个
  volantis.dom.switcher = volantis.dom.$(document.querySelector('#l_header .switcher .s-search')); // 搜索按钮   移动端 1个
  volantis.dom.header = volantis.dom.$(document.getElementById('l_header')); // 移动端导航栏
  volantis.dom.search = volantis.dom.$(document.querySelector('#l_header .m_search')); // 搜索框 桌面端 移动端 1个
  volantis.dom.mPhoneList = volantis.dom.$(document.querySelectorAll('#l_header .m-phone .list-v')); //  手机端 子菜单 多个
</script>

<script>
  
  volantis.css("https://unpkg.com/volantis-static@0.0.1654736714924/libs/@fortawesome/fontawesome-free/css/all.min.css");
  
  
  
</script>

<!-- required -->


<!-- internal -->

<script src="/js/app.js"></script>






<!-- rightmenu要在darkmode之前（ToggleButton） darkmode要在comments之前（volantis.dark.push）-->



<script>
  function loadIssuesJS() {
    
      const sites_api = document.getElementById('sites-api');
      if (sites_api != undefined && typeof SitesJS === 'undefined') {
        volantis.js("/js/plugins/tags/sites.js")
      }
    
    
      const friends_api = document.getElementById('friends-api');
      if (friends_api != undefined && typeof FriendsJS === 'undefined') {
        volantis.js("/js/plugins/tags/friends.js")
      }
    
    
      const contributors_api = document.getElementById('contributors-api');
      if (contributors_api != undefined && typeof ContributorsJS === 'undefined') {
        volantis.js("/js/plugins/tags/contributors.js")
      }
    
  };
  loadIssuesJS()
  volantis.pjax.push(()=>{
    loadIssuesJS();
  })

</script>




  <script defer src="https://unpkg.com/volantis-static@0.0.1654736714924/libs/vanilla-lazyload/dist/lazyload.min.js"></script>
<script>
  // https://www.npmjs.com/package/vanilla-lazyload
  // Set the options globally
  // to make LazyLoad self-initialize
  window.lazyLoadOptions = {
    elements_selector: ".lazyload",
    threshold: 0
  };
  // Listen to the initialization event
  // and get the instance of LazyLoad
  window.addEventListener(
    "LazyLoad::Initialized",
    function (event) {
      window.lazyLoadInstance = event.detail.instance;
    },
    false
  );
  document.addEventListener('DOMContentLoaded', function () {
    lazyLoadInstance.update();
  });
  document.addEventListener('pjax:complete', function () {
    lazyLoadInstance.update();
  });
</script>




  

<script>
  window.FPConfig = {
	delay: 0,
	ignoreKeywords: ["#"],
	maxRPS: 6,
	hoverDelay: 0
  };
</script>
<script defer src="https://unpkg.com/volantis-static@0.0.1654736714924/libs/flying-pages/flying-pages.min.js"></script>









      <script>
  volantis.layoutHelper("comments",`<div id="giscus_container"></div>`)

  volantis.giscus = {};

  function check_giscus() {
    if (volantis.dark.mode === "dark") {
      volantis.giscus.Theme = 'dark';
    } else {
      volantis.giscus.Theme = 'light';
    }

    return document.getElementById("giscus_container");
  }

  function pjax_giscus() {
    const HEAD = check_giscus();
    if (!HEAD) return;
    let cfg = Object.assign({"theme":{"light":"light","dark":"dark"}},pdata.commentConfig)
    const script = document.createElement('script');
    script.setAttribute('src', 'https://giscus.app/client.js');
    Object.keys(cfg).forEach(k=>{
      if (k != "theme") {
        script.setAttribute('data-'+k, cfg[k]);
      }
    })
    script.setAttribute('data-theme', volantis.giscus.Theme);
    script.setAttribute('crossorigin', "anonymous");
    HEAD.appendChild(script);
  }

  function dark_giscus() {
    const HEAD = check_giscus();
    if (!HEAD) return;

    const message = {
      setConfig: {
        theme: volantis.giscus.Theme
      }
    };
    const giscusIframe = document.querySelector('iframe.giscus-frame');
    giscusIframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
  }
  pjax_giscus();
  volantis.pjax.push(pjax_giscus);
  volantis.dark.push(dark_giscus);
</script>

    





<!-- optional -->

  <script>
  const SearchServiceDataPathRoot = ("/" || "/").endsWith("/") ?
    "/" || "/" :
    "//" || "/";
  const SearchServiceDataPath = SearchServiceDataPathRoot + "content.json";

  function loadSearchScript() {
    // see: layout/_partial/scripts/_ctrl/cdnCtrl.ejs
    return volantis.js("/js/search/hexo.js");
  }

  function loadSearchService() {
    loadSearchScript();
    document.querySelectorAll(".input.u-search-input").forEach((e) => {
      e.removeEventListener("focus", loadSearchService, false);
    });

    document.querySelectorAll(".u-search-form").forEach((e) => {
      e.addEventListener("submit", (event) => {
        event.preventDefault();
      }, false);
    });
  }

  // 打开并搜索 字符串 s
  function OpenSearch(s) {
    if (typeof SearchService === 'undefined')
      loadSearchScript().then(() => {
        SearchService.setQueryText(s);
        SearchService.search();
      });
    else {
      SearchService.setQueryText(s);
      SearchService.search();
    }
  }

  // 访问含有 ?s=xxx  的链接时打开搜索 // 与搜索引擎 structured data 相关: /scripts/helpers/structured-data/lib/config.js
  if (window.location.search && /^\?s=/g.test(window.location.search)) {
    let queryText = decodeURI(window.location.search)
      .replace(/\ /g, "-")
      .replace(/^\?s=/g, "");
    OpenSearch(queryText);
  }

  // 搜索输入框获取焦点时加载搜索
  document.querySelectorAll(".input.u-search-input").forEach((e) => {
    e.addEventListener("focus", loadSearchService, false);
  });
</script>







  <script>



  function pjax_highlightjs_copyCode(){
    if (!(document.querySelector(".highlight .code pre") ||
      document.querySelector(".article pre code"))) {
      return;
    }
    VolantisApp.utilCopyCode(".highlight .code pre, .article pre code")
  }
  volantis.requestAnimationFrame(pjax_highlightjs_copyCode)
  volantis.pjax.push(pjax_highlightjs_copyCode)

</script>












  <script>
  function load_swiper() {
    if (!document.querySelectorAll(".swiper-container")[0]) return;
    volantis.css("https://unpkg.com/volantis-static@0.0.1654736714924/libs/swiper/swiper-bundle.min.css");
    volantis.js("https://unpkg.com/volantis-static@0.0.1654736714924/libs/swiper/swiper-bundle.min.js").then(() => {
      pjax_swiper();
    });
  }

  load_swiper();

  function pjax_swiper() {
    volantis.swiper = new Swiper('.swiper-container', {
      slidesPerView: 'auto',
      spaceBetween: 8,
      centeredSlides: true,
      loop: true,
      pagination: {
        el: '.swiper-pagination',
        clickable: true,
      },
      navigation: {
        nextEl: '.swiper-button-next',
        prevEl: '.swiper-button-prev',
      },
    });
  }

  volantis.pjax.push(() => {
    if (!document.querySelectorAll(".swiper-container")[0]) return;
    if (typeof volantis.swiper === "undefined") {
      load_swiper();
    } else {
      pjax_swiper();
    }
  });
</script>


<!-- pjax 标签必须存在于所有页面 否则 pjax error -->
<pjax>

</pjax>

<script>
  function listennSidebarTOC() {
    const navItems = document.querySelectorAll(".toc li");
    if (!navItems.length) return;
    let targets = []
    const sections = [...navItems].map((element) => {
      const link = element.querySelector(".toc-link");
      const target = document.getElementById(
        decodeURI(link.getAttribute("href")).replace("#", "")
      );
      targets.push(target)
      // 解除 a 标签 href 的 锚点定位, a 标签 href 的 锚点定位 会随机启用?? 产生错位???
      link.setAttribute("onclick","return false;")
      link.setAttribute("toc-action","toc-"+decodeURI(link.getAttribute("href")).replace("#", ""))
      link.setAttribute("href","/")
      // 配置 点击 触发新的锚点定位
      link.addEventListener("click", (event) => {
        event.preventDefault();
        // 这里的 addTop 是通过错位使得 toc 自动展开.
        volantis.scroll.to(target,{addTop: 5, observer:true})
        // Anchor id
        history.pushState(null, document.title, "#" + target.id);
      });
      return target;
    });

    function activateNavByIndex(target) {
      if (target.classList.contains("active-current")) return;

      document.querySelectorAll(".toc .active").forEach((element) => {
        element.classList.remove("active", "active-current");
      });
      target.classList.add("active", "active-current");
      let parent = target.parentNode;
      while (!parent.matches(".toc")) {
        if (parent.matches("li")) parent.classList.add("active");
        parent = parent.parentNode;
      }
    }

    // 方案一：
    volantis.activateNavIndex=0
    activateNavByIndex(navItems[volantis.activateNavIndex])
    volantis.scroll.push(()=>{
      if (targets[0].getBoundingClientRect().top >= 0) {
        volantis.activateNavIndex = 0
      }else if (targets[targets.length-1].getBoundingClientRect().top < 0) {
        volantis.activateNavIndex = targets.length-1
      } else {
        for (let index = 0; index < targets.length; index++) {
          const target0 = targets[index];
          const target1 = targets[(index+1)%targets.length];
          if (target0.getBoundingClientRect().top < 0&&target1.getBoundingClientRect().top >= 0) {
            volantis.activateNavIndex=index
            break;
          }
        }
      }
      activateNavByIndex(navItems[volantis.activateNavIndex])
    })

    // 方案二：
    // IntersectionObserver 不是完美精确到像素级别 也不是低延时性的
    // function findIndex(entries) {
    //   let index = 0;
    //   let entry = entries[index];
    //   if (entry.boundingClientRect.top > 0) {
    //     index = sections.indexOf(entry.target);
    //     return index === 0 ? 0 : index - 1;
    //   }
    //   for (; index < entries.length; index++) {
    //     if (entries[index].boundingClientRect.top <= 0) {
    //       entry = entries[index];
    //     } else {
    //       return sections.indexOf(entry.target);
    //     }
    //   }
    //   return sections.indexOf(entry.target);
    // }
    // function createIntersectionObserver(marginTop) {
    //   marginTop = Math.floor(marginTop + 10000);
    //   let intersectionObserver = new IntersectionObserver(
    //     (entries, observe) => {
    //       let scrollHeight = document.documentElement.scrollHeight;
    //       if (scrollHeight > marginTop) {
    //         observe.disconnect();
    //         createIntersectionObserver(scrollHeight);
    //         return;
    //       }
    //       let index = findIndex(entries);
    //       activateNavByIndex(navItems[index]);
    //     }, {
    //       rootMargin: marginTop + "px 0px -100% 0px",
    //       threshold: 0,
    //     }
    //   );
    //   sections.forEach((element) => {
    //     element && intersectionObserver.observe(element);
    //   });
    // }
    // createIntersectionObserver(document.documentElement.scrollHeight);
  }

  document.addEventListener("DOMContentLoaded", ()=>{
    volantis.requestAnimationFrame(listennSidebarTOC)
  });
  document.addEventListener("pjax:success", ()=>{
    volantis.requestAnimationFrame(listennSidebarTOC)
  });
</script>



<script>
  document.onreadystatechange = function () {
    if (document.readyState == 'complete') {
      // 页面加载完毕 样式加载失败，或是当前网速慢，或是开启了省流模式
      const { saveData, effectiveType } = navigator.connection || navigator.mozConnection || navigator.webkitConnection || {}
      if (getComputedStyle(document.querySelector("#safearea"), null)["display"] == "none" || saveData || /2g/.test(effectiveType)) {
        document.querySelectorAll(".reveal").forEach(function (e) {
          e.style["opacity"] = "1";
        });
        document.querySelector("#safearea").style["display"] = "block";
      }
    }
  }
</script>


  <script type="application/ld+json">[{"@context":"http://schema.org","@type":"Organization","name":"欢迎来到我的个人博客~","url":"http://8.219.11.28/","logo":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png","width":192,"height":192}},{"@context":"http://schema.org","@type":"Person","name":"天明","image":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png"},"url":"http://8.219.11.28/","sameAs":["https://github.com/volantis-x"],"description":"这些技术大部分是自己总结的，非官方"},{"@context":"http://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"http://8.219.11.28/","name":"欢迎来到我的个人博客~"}},{"@type":"ListItem","position":3,"item":{"@id":"http://8.219.11.28/2024/02/23/前后端-SpringMVC课堂笔记/"}}]},{"@context":"http://schema.org","@type":"WebSite","name":"欢迎来到我的个人博客~","url":"http://8.219.11.28/","keywords":null,"description":"这些技术大部分是自己总结的，非官方","author":{"@type":"Person","name":"天明","image":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png"},"url":"http://8.219.11.28/","description":"这些技术大部分是自己总结的，非官方"},"publisher":{"@type":"Organization","name":"欢迎来到我的个人博客~","url":"http://8.219.11.28/","logo":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png","width":192,"height":192}},"potentialAction":{"@type":"SearchAction","name":"Site Search","target":{"@type":"EntryPoint","urlTemplate":"http://8.219.11.28?s={search_term_string}"},"query-input":"required name=search_term_string"}},{"@context":"http://schema.org","@type":"BlogPosting","description":"这些技术大部分是自己总结的，非官方","inLanguage":"en","mainEntityOfPage":{"@type":"WebPage","@id":"http://8.219.11.28/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-SpringMVC%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/"},"author":{"@type":"Person","name":"天明","image":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png"},"url":"http://8.219.11.28/"},"publisher":{"@type":"Organization","name":"欢迎来到我的个人博客~","logo":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png","width":192,"height":192}},"url":"http://8.219.11.28/2024/02/23/%E5%89%8D%E5%90%8E%E7%AB%AF-SpringMVC%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/","wordCount":0,"datePublished":"2024-02-23T14:27:45.499Z","dateModified":"2024-01-15T11:27:56.531Z","image":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png","width":192,"height":192}}]</script>



      
        <!--
  pjax重载区域接口：
  1.  <pjax></pjax> 标签 pjax 标签必须存在于所有页面 否则 pjax error
  2.  script[data-pjax]
  3.  .pjax-reload script
  4.  .pjax
-->



<script src="https://unpkg.com/volantis-static@0.0.1654736714924/libs/pjax/pjax.min.js"></script>


<script>
    var pjax;
    document.addEventListener('DOMContentLoaded', function () {
      pjax = new Pjax({
        elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox]):not([onclick="return false;"]):not([onclick="return!1"]):not([target="_blank"]):not([target="view_window"]):not([href$=".xml"])',
        selectors: [
          "head title",
          "head meta[name=keywords]",
          "head meta[name=description]",
          
          "#l_main",
          "#pjax-header-nav-list",
          ".pjax",
          "pjax", // <pjax></pjax> 标签
          "script[data-pjax], .pjax-reload script" // script标签添加data-pjax 或 script标签外层添加.pjax-reload 的script代码段重载
        ],
        cacheBust: false,   // url 地址追加时间戳，用以避免浏览器缓存
        timeout: 5000,
        
      });
    });

    document.addEventListener('pjax:send', function (e) {
      //window.stop(); // 相当于点击了浏览器的停止按钮

      try {
        var currentUrl = window.location.pathname;
        var targetUrl = e.triggerElement.href;
        var banUrl = [""];
        if (banUrl[0] != "") {
          banUrl.forEach(item => {
            if(currentUrl.indexOf(item) != -1 || targetUrl.indexOf(item) != -1) {
              window.location.href = targetUrl;
            }
          });
        }
      } catch (error) {}

      // 使用 volantis.pjax.send 方法传入pjax:send回调函数 参见layout/_partial/scripts/global.ejs
      volantis.pjax.method.send.start();
    });

    document.addEventListener('pjax:complete', function () {
      // 使用 volantis.pjax.push 方法传入重载函数 参见layout/_partial/scripts/global.ejs
      volantis.pjax.method.complete.start();
    });

    document.addEventListener('pjax:error', function (e) {
      if(volantis.debug) {
        console.error(e);
        console.log('pjax error: \n' + JSON.stringify(e));
      }else{
        // 使用 volantis.pjax.error 方法传入pjax:error回调函数 参见layout/_partial/scripts/global.ejs
        volantis.pjax.method.error.start();
        window.location.href = e.triggerElement.href;
      }
    });
</script>

      
    </div>
    <!-- import body_end begin-->
    <!-- import body_end end-->
    <!-- Custom Files bodyEnd begin-->
    
    <!-- Custom Files bodyEnd end-->
    <!-- front-matter body_end begin -->
    <!-- front-matter body_end end -->
  </body>
</html>
